javascript - ionicframework - ¿Ionic Framework resolveLocalFileSystemURL asincrónico?
ionic v2 documentation (2)
Las funciones anónimas proporcionadas a window.resolveLocalFileSystemURL
y reader.readEntries
se invocan de forma asíncrona. La "forma AngularJS" para manejar esto es usar el servicio $q
para crear y devolver una promesa.
function countDirPromise(path){
//create $q.defer object
var q = $q.defer();
var count = 0;
console.log('Counting the files inside '+path);
$window.resolveLocalFileSystemURL(path,
function onUrlSuccess(fileSystem) {
var reader = fileSystem.createReader();
reader.readEntries(
function onReaderSuccess(entries) {
var i;
for (i=0; i<entries.length; i++) {
console.log('File name ' + entries[i].name + ' added to count');
count++;
}
//resolve with count
q.resolve(count);
},
function onReaderError(err) {
console.log(err);
//reject with error
q.reject(err);
}
);
}, function onUrlError(err) {
console.log(err);
//reject with error
q.reject(err);
}
);
//return count promise
return q.promise;
}
Como puede ver, hay cuatro funciones anidadas: onUrlSuccess
, onUrlError
, onReaderSuccess
y onReaderError
. Esas funciones se invocan de forma asincrónica. La promesa se resuelve con el count
valores si se onUrlSuccess
y la función anidada onReaderSuccess
. La promesa se rechaza con un error si se onUrlError
función onReaderError
o la función onReaderError
.
Uso
var countPromise = countDirPromise(cordova.file.dataDirectory +'/Images/');
console.log('Hello ');
countPromise.then(function onSuccess(count) {
console.log('Count of directory '+count);
//return to chain data
return count;
}).catch(function onReject(err) {
console.log(err);
//throw to chain rejection
throw err;
}).then(anotherSuccessFn, anotherRejectFn);
Las funciones proporcionadas a los métodos .then
y .catch
son invocadas asincrónicamente por el servicio $q
.
Para obtener más información, consulte AngularJS $q
Service API Reference - The Diferred API
Usando ngCordova
El enfoque alternativo es usar las promesas de servicio $q
devueltas por la API ngCordova $ cordovaFile .
function countDirPromise(path){
var count = 0;
console.log('Counting the files inside '+path);
var promise = $cordovaFile.checkDir(path);
var derivedPromise = promise.then(
function onSuccess(fileSystem) {
var q = $q.defer()
var reader = fileSystem.createReader();
reader.readEntries(
function onReaderSuccess(entries) {
var i;
for (i=0; i<entries.length; i++) {
console.log('File name ' + entries[i].name + ' added to count');
count++;
}
//resolve with count
q.resolve(count);
},
function onReaderError(err) {
console.log(err);
//reject with error
q.reject(err);
}
);
//return to chain promise
return q.promise;
};
});
return derivedPromise;
}
Estoy llamando a una función desde mi controlador AngularJS. Cuando la función complete la ejecución, me gustaría imprimir el resultado después de la llamada a la función.
Este código está dentro del controlador, que se llama al toque
//count the number of files inside a directory
var count = countDir(cordova.file.dataDirectory +'/Images/');
console.log('Hello ');
console.log('Count of directory '+count);
Aquí está la función countDir. Esta función encuentra la cantidad de archivos en un directorio y luego devuelve la cuenta
function countDir(path){
var count = 0;
console.log('Counting the files inside '+path);
window.resolveLocalFileSystemURL(path,
function (fileSystem) {
var reader = fileSystem.createReader();
reader.readEntries(
function (entries) {
var i;
for (i=0; i<entries.length; i++) {
console.log('File name ' + entries[i].name + ' added to count');
count++;
}
},
function (err) {
console.log(err);
}
);
}, function (err) {
console.log(err);
}
);
return count;
}
El desafío al que me enfrento es que mi código de llamada imprime primero 'Hola' y 'Número del directorio 0' y luego todo lo que está dentro de countDir se imprime.
¿La llamada a countDir()
asincrónica? De ser así, ¿cómo puedo asegurar que mi código de llamada countDir()
una vez que countDir()
haya devuelto un resultado?
Puede pasar la devolución de llamada a la función countDir y llamarla después del ciclo for.
var count = countDir(cordova.file.dataDirectory +'/Images/', function(count){
console.log('Hello ');
console.log('Count of directory '+count);
});
Y en la definición de la función.
function countDir(path, callback){
...
for (i=0; i<entries.length; i++) {
...
}
callback(count);
...
}