4

I am building a native desktop application in javascript using CEF, And I have API to access filesystem from CEF. I have a senario, in which I need to get names of all files(there could be trees of directories) within a particular directory. I need to get result array, I am using jquery promises. What I don't understand is: when do I resolve the promise to get final result array?

/*read all directories under this and get path*/
    var result = [];
    function _processEntries(dirPath) {
        var dirEntry = new NativeFileSystem.DirectoryEntry(dirPath), deferred = new $.Deferred();

        /*async call*/
        dirEntry.createReader().readEntries(
            function (entries) {
                for (var i = 0; i < entries.length; i++) {
                    if (entries[i].isDirectory) {
                        _processEntries(entries[i].fullPath).done(function () {
                            deferred.resolve(result);
                        });
                    } else {
                        result.push(entries[i].fullPath);
                    }
                }
            },
            function (error) {
                console.log("Failed while reading dir:", error);
            }
        );
        return deferred.promise();
    }

// Calling function

_processEntries("C:/Users/abc").done(function(result){
    console.log("FILES ARRAY:",result);
});

Please suggest any other technique if I am doing it wrong :)

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Darshan
  • 750
  • 7
  • 19
  • Try not to use jQuery promises when you could easily use much better promise libraries. – Bergi Feb 23 '15 at 16:07

2 Answers2

0

Mmmm i see few errors you resolve the entire promise when the first child returns, you must wait for all your child directory finish there respective promise, and your are resolve a global variable not internal, look this example with the changes:

function _processEntries(dirPath) {
    var result = [];
    var dirEntry = new NativeFileSystem.DirectoryEntry(dirPath), deferred = new $.Deferred();

    /*async call*/
    dirEntry.createReader().readEntries(
        function (entries) {
            var promises = [];
            for (var i = 0; i < entries.length; i++) {
                if (entries[i].isDirectory) {
                    promises.push(_processEntries(entries[i].fullPath));
                } else {
                    result.push(entries[i].fullPath);
                }
            }

            if(promises.length === 0) {
              deferred.resolve(result);
            } else {
               $.when.apply($,promises).done(function() {
                result.concat(arguments);
                deferred.resolve(result);
              })
            }
        },
        function (error) {
            console.log("Failed while reading dir:", error);
        }
    );
    return deferred.promise();
}
Jesús Quintana
  • 1,803
  • 13
  • 18
0

when do I resolve the promise

Immediately when the asynchronous call has ended. You would have the deferred antipattern otherwise. Avoiding that, you can work with promises everywhere, and use proper composition with them.

Also, you should not initialise your result variable outside of the _processEntries function - you'd get huge problems with calling the function multiple times.

function getDirectoryEntries(dirPath) {
    // a promise helper function
    var dirEntry = new NativeFileSystem.DirectoryEntry(dirPath),
        deferred = new $.Deferred();
    dirEntry.createReader().readEntries(deferred.resolve, deferred.reject);
    return deferred.promise();
}
function _processEntries(dirPath) {
    return getDirectoryEntries(dirPath).then(function (entries) {
        var promises = [];
        for (var i = 0; i < entries.length; i++) {
             if (entries[i].isDirectory) {
                  promises.push(_processEntries(entries[i].fullPath));
             } else {
                  promises.push($.when(entries[i].fullPath));
             }
        }
        return $.when.apply($, promises).then(function() {
             return [].concat.apply([], arguments);
        });
    });
}

Call it like this:

_processEntries("C:/Users/abc").then(function(result){
    console.log("FILES ARRAY:",result);
}, function (error) {
    console.log("Failed while reading dir:", error);
});
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375