Ivan Bacher
Ivan Bacher

Reputation: 6154

Recursive promises in Angular JS

I want to traverse through a html5 file system and have some sort of notification once all files have been traversed.

Im using filer which is a wrapper for the html file system library

in order to start the recursive file system walker im using this:

filerService.ls(filerService.fs.root, function(entries){
  for(var i = 0; i < entries.length; i ++) {
    traverseFileTree(entries[i]);
  }
});

the recursive function:

function traverseFileTree(item) {

    if(item.isFile) {
         console.log("item is file: " + item.name); 
         //do something with file here

    } else if (item.isDirectory) {
        console.log("item is directory: " + item.name); 

        filerService.ls(item, function(entries) {

            for(var i = 0; i < entries.length; i ++) {
                traverseFileTree(entries[i]);
            }
        }); 
    }
};

Now I would like to do the following:

var promise = walkFileTree() //this method should start the recursive methods and return a promise

promise.then(function(){
  //notify user that the filewalker has completed
})

anyone have some pointers on how this can be achieved?

Upvotes: 2

Views: 1992

Answers (1)

Nikos Paraskevopoulos
Nikos Paraskevopoulos

Reputation: 40296

It can be accomplished using an array of promises (one for each subdirectory) and $q.all(). An untested outline of the solution would be:

function walkFileTree(item) {
    var d = $q.defer(), promises = [d.promise]; // we need at least one promise because we do not know beforehand the number of included directories
    if( typeof(item) === "undefined" ) item = filerService.fs.root;
    filerService.ls(item, function(entries){
        for(var i = 0; i < entries.length; i ++) {
            promises.push(traverseFileTree(entries[i]));
        }
        d.resolve();
    });
    return $q.all(promises);
}

function traverseFileTree(item) {
    var d = $q.defer();
    if(item.isFile) {
        console.log("item is file: " + item.name);
        //do something with file here
        d.resolve();
        return d.promise;
    }
    else if (item.isDirectory) {
        console.log("item is directory: " + item.name); 

        return walkFileTree(item);
    }
};

Note that walkFileTree(item) will iterate the item, while walkFileTree() will iterate the root.

As I said this is untested and will probably need tweaking, but it demonstrates (I think) the outline for a solution.

Upvotes: 3

Related Questions