ionicframework framework documento docs javascript angularjs ionic-framework angular-promise ngcordova

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 } );