javascript - framework - ionic components
¿Ionic Framework resolveLocalFileSystemURL asincrónico? (3)
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);
...
}
Sí, el .resolveLocalFileSystemUrl es asíncrono; puedes abordar tu problema usando la promesa de $ q:
function countDir(path){
var deff = $q.defer();
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++;
}
deff.resolve(count);
},
function (err) {
console.log(err);
deff.reject(err);
}
);
}, function (err) {
console.log(err);
deff.reject(err);
}
);
return deff.promise;
}
Y consumirlo como:
var count =0 ;
countDir(cordova.file.dataDirectory +''/Images/'')
.then( function(result){ count = result},
function(err){ //handle error }
);