Ionic Framework resolveLocalFileSystemURL 是异步的吗?

Is Ionic Framework resolveLocalFileSystemURL Asynchronous?

我正在从我的 AngularJS 控制器调用一个函数。当函数完成执行时,我想打印函数调用后的结果。

此代码在控制器内部,称为on-tap

  //count the number of files inside a directory
   var count = countDir(cordova.file.dataDirectory +'/Images/');
   console.log('Hello ');
   console.log('Count of directory '+count);

这是 countDir 函数。此函数查找目录中的文件数,然后 returns 倒数

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

我面临的挑战是,我的调用代码首先打印 'Hello' 和 'Count of directory 0',然后打印 countDir 中的所有内容。

countDir()的调用是异步的吗?如果是这样,我如何确保我的调用代码在 countDir() 返回结果后继续执行。

您可以将回调传递给 countDir 函数,并在 for 循环之后调用它。

 var count = countDir(cordova.file.dataDirectory +'/Images/', function(count){
   console.log('Hello ');
   console.log('Count of directory '+count);
});

并且在函数的定义中。

function countDir(path, callback){
  ...
     for (i=0; i<entries.length; i++)  { 
       ... 
    }
    callback(count);
  ...
}

是的,.resolveLocalFileSystemUrl 是异步的;您可以使用 $q promise:

解决您的问题
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; 
}

并将其消费为:

var count =0 ;
countDir(cordova.file.dataDirectory +'/Images/')
       .then( function(result){ count = result},
              function(err){ //handle error }
             );

提供给 window.resolveLocalFileSystemURLreader.readEntries 的匿名函数是异步调用的。 "AngularJS way" 处理此问题是使用 $q 服务来创建和 return 承诺。

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

如您所见,有四个嵌套函数:onUrlSuccessonUrlErroronReaderSuccessonReaderError。这些函数被异步调用。如果 onUrlSuccess 和嵌套函数 onReaderSuccess 都被调用,则 promise 解析为值 count。如果 onUrlError 函数或 onReaderError 函数被调用,承诺将被错误拒绝。

用法

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

提供给 .then.catch 方法的功能由 $q 服务异步调用。

有关详细信息,请参阅 AngularJS $q Service API Reference -- The Deferred API


使用 ngCordova

另一种方法是使用 ngCordova $cordovaFile API 编写的 $q 服务承诺 return。

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