Is Ionic Framework resolveLocalFileSystemURL Asynchronous?

若如初见. 提交于 2020-01-03 21:09:41

问题


I am calling a function from my AngularJS controller. 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

  //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. 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.

Is the call to countDir() asynchronous? If so, how can I ensure that my calling code proceeds once countDir() has returned a result.


回答1:


The anonymous functions furnished to both window.resolveLocalFileSystemURL and reader.readEntries are invoked asynchronously. The "AngularJS way" to handle this is to use the $q service to create and return a 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. Those functions get invoked asynchronously. The promise resolves with the value count if both onUrlSuccess and the nested function onReaderSuccess get invoked. The promise is rejected with an error if either the onUrlError function or onReaderError function get invoked.

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.

For more information, see AngularJS $q Service API Reference -- The Deferred API


Using ngCordova

The alternative approach is to use the $q service promises returned by the ngCordova $cordovaFile API.

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



回答2:


Yes, the .resolveLocalFileSystemUrl is async; you could tackle your issue using $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; 
}

And consume it as:

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



回答3:


You can pass callback to countDir function and call it after the for loop.

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


来源:https://stackoverflow.com/questions/39314502/is-ionic-framework-resolvelocalfilesystemurl-asynchronous

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!