Search code examples
javascripthtmlrecursioncallbackjaydata

Handling callback in recursive asynchronous calls


I am using Jaydata as API for HTML5 indexedDB. I have a table in indexedDB where I need to query recursively. I need a callback when entire process is completed. Following is the recursive function. I need to have a callback when everything is done.

function getData(idValue) {
    myDB.MySplDB
        .filter( function(val) {
            return val.ParentId == this.parentId;
        }, {parentId: idvalue})
        .toArray( function(vals) {
            if(vals.length < 1) {
                // some operation to store the value
            } else {
                for (var j=0;j<vals.length;j++) {
                    getData(vals[j].Id);
                }
            }
        });
}

Adding .done(function(){...}); to .toArray doesn't work since it gets called before completion.


Solution

  • (Disclaimer: I work for JayData)

    To wait for the finish of the entire process you need to use promises. You always have to return a promise. In the loop it gets tricky, return a super promise. So the code should be something like this:

    function getData(idValue) {
        return myDB.MySplDB
        .filter( function(val) {
            return val.ParentId == this.parentId;
        }, {parentId: idvalue})
        .toArray( function(vals) {
            if(vals.length < 1) {
                // some operation to store the value
                // important: return a promise from here, like:
                return myDB.saveChanges(); 
            } else {
                var promises = [];
                for (var j=0;j<vals.length;j++) {
                    promises.push(getData(vals[j].Id));
                }
                return $.when.apply(this, promises);
            }
        });
    }
    
    getData(1)
    .then(function() {
            // this will run after everything is finished
    });
    

    remarks:

    1. this example uses jQuery promises, so you'll need jQuery 1.8+ $.when uses varargs hence we need the apply

    2. this can work with q promise with a slightly different syntax