1

I tried to build a function with Cordova which gives me a JSON object that looks as follows:

{
  "file:///storage/emulated/0/Android/data/test/files/data/bla.txt": "bla.txt",
  "file:///storage/emulated/0/Android/data/test/files/data/HelloWorld.txt": "HelloWorld.txt",
  "file:///storage/emulated/0/Android/data/test/files/data/RSC/picture-1469199158993.jpg": "picture-1469199158993.jpg",
  "file:///storage/emulated/0/Android/data/test/files/data/RSC/picture-1469199665434.jpg": "picture-1469199665434.jpg",
  "file:///storage/emulated/0/Android/data/test/files/data/API-Test/test/datFile.txt": "datFile.txt",
  "file:///storage/emulated/0/Android/data/test/files/data/RSC/thumbnails/picture-1469199158993.jpg": "picture-1469199158993.jpg",
  "file:///storage/emulated/0/Android/data/test/files/data/RSC/thumbnails/picture-1469199665434.jpg": "picture-1469199665434.jpg"
}

My problem is that the Cordova functions are async so my function returns an empty object.

Here is my solution so far:

var dirObj = new Object();

function getFiles(fullPath, callback){
    dirObj = new Object();

    window.resolveLocalFileSystemURL(fullPath, addFileEntry, function(e){
            console.error(e);
    });

    return JSON.stringify(dirObj);    
}

var addFileEntry = function (entry) {
  var dirReader = entry.createReader();
  dirReader.readEntries(
    function (entries) {
      var fileStr = "";
      for (var i = 0; i < entries.length; i++) {
        if (entries[i].isDirectory === true) {
          addFileEntry(entries[i]);
        } else {
          dirObj[entries[i].nativeURL] = entries[i].name;
          console.log(entries[i].fullPath);
        }
      }
    },
    function (error) {
      console.error("readEntries error: " + error.code);
    }
  );
};

Note: Promise() is not an option because the function have to work on Chrome 30.0 and Promise() is avaible since 32.0 (src).

Durzan
  • 23
  • 4
  • Can you use callbacks or a promise polyfill (e.g. Bluebird)? – gcampbell Jul 26 '16 at 10:37
  • Possible duplicate of [Wait for async task to finish](http://stackoverflow.com/questions/18729761/wait-for-async-task-to-finish) – AxelH Jul 26 '16 at 10:53
  • @AxelH and how would you decide if the recursive function is finished to call the callback? The recursive function calls themself are async. – Durzan Jul 26 '16 at 11:31
  • If the directory reader don't give you the choice, then you are going to count each entry and exit for each async function call (increment at start and decrement at exit) . The main call should be done when the counter is at zero. This is ugly ... so I would try to create this JSON on an other way. – AxelH Jul 26 '16 at 11:44

2 Answers2

0

I found a solution similar to @AxelH suggested solution. I used an array: Everytime I called the function addFileEntry I pushed a id into the array. When the function was finished I removed the id from the array. I called then the callback function if the array is empty.

Thank you @AxelH for your help and thanks @gcampbell for mentioning bluebird which I didn't know and will use for an other async problem in javascript.

Durzan
  • 23
  • 4
  • Yes, using an array is the same as a incrementing variable, but a bit more heavy since you need to generate the id and then find it again. Let me write it my way so you can close this question if this is ok for you – AxelH Jul 27 '16 at 08:26
  • Sure. I think it would be helpful for others, too. – Durzan Jul 27 '16 at 11:35
0
var dirObj;

function getFiles(fullPath, callback){
    dirObj = new Object();

    window.resolveLocalFileSystemURL(fullPath, addFileEntry, function(e){
            console.error(e);
    });
}

var counter = 0;

var addFileEntry = function (entry) {
  ++counter;
  var dirReader = entry.createReader();
  [...] //you probably should do it in the readEntries function to since this is async to (as you said), because this could still run while the following line might be executed. If so, just add the same if(...) callback();
  if(--counter == 0)
      callBack();
};

function callBack(){
   var json = JSON.stringify(dirObj);
   //Do what you need with it.
}
AxelH
  • 14,325
  • 2
  • 25
  • 55