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




ngcordova