简体   繁体   English

Ionic Framework是否为resolveLocalFileSystemURL异步?

[英]Is Ionic Framework resolveLocalFileSystemURL Asynchronous?

I am calling a function from my AngularJS controller. 我从我的AngularJS控制器调用一个函数。 When the function completes execution, I would like to print the result after the function call. 当函数完成执行时,我想在函数调用后打印结果。

This code is inside the controller, which is called on-tap 此代码位于控制器内部,称为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);

Here is the countDir function. 这是countDir函数。 This function finds the number of files in a directory and then returns the count back 此函数查找目录中的文件数,然后返回计数

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

The challenge that I am facing is that, my calling code first prints 'Hello' and 'Count of directory 0' and then everything inside countDir is printed. 我面临的挑战是,我的调用代码首先打印'Hello'和'Count of directory 0',然后打印countDir中的所有内容。

Is the call to countDir() asynchronous? countDir()的调用是否异步? If so, how can I ensure that my calling code proceeds once countDir() has returned a result. 如果是这样,一旦countDir()返回结果,我如何确保我的调用代码继续进行。

Yes, the .resolveLocalFileSystemUrl is async; 是的,.resolveLocalFileSystemUrl是异步的; you could tackle your issue using $q promise: 你可以使用$ 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; 
}

And consume it as: 并将其消费为:

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

The anonymous functions furnished to both window.resolveLocalFileSystemURL and reader.readEntries are invoked asynchronously. 提供给window.resolveLocalFileSystemURLreader.readEntries的匿名函数是异步调用的。 The "AngularJS way" to handle this is to use the $q service to create and return a promise. 处理此问题的“AngularJS方法”是使用$q服务来创建并返回一个promise。

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

As you can see, there are four nested function: onUrlSuccess , onUrlError , onReaderSuccess , and onReaderError . 如您所见,有四个嵌套函数: onUrlSuccessonUrlErroronReaderSuccessonReaderError Those functions get invoked asynchronously. 这些函数是异步调用的。 The promise resolves with the value count if both onUrlSuccess and the nested function onReaderSuccess get invoked. 如果调用onUrlSuccess和嵌套函数onReaderSuccess则promise将使用值count解析。 The promise is rejected with an error if either the onUrlError function or onReaderError function get invoked. 如果调用onUrlError函数或onReaderError函数,则会拒绝承诺错误。

Usage 用法

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

The functions furnished to both the .then and .catch methods are invoked asynchronously by the $q service. 提供给双方的功能.then.catch方法由异步调用$q服务。

For more information, see AngularJS $q Service API Reference -- The Deferred API 有关更多信息,请参阅AngularJS $q服务API参考 - 延迟API


Using ngCordova 使用ngCordova

The alternative approach is to use the $q service promises returned by the ngCordova $cordovaFile API . 另一种方法是使用ngCordova $ cordovaFile API返回的$q服务承诺。

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

You can pass callback to countDir function and call it after the for loop. 您可以将回调传递给countDir函数,并在for循环后调用它。

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

And in the definition of the function. 并在功能的定义。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM