Question

I have an array I want to iterate and, based on its length, make an async call to obtain some data I want to add to a new array.

The pseudocode looks like:

var path =["Cars", "Owners", "Name"];
var parentObject = mainObject;

getChildren (path, parentObject){
    var deferred = new JQuery.Deferred();
    var pathSplit = path.split(".");
    var nestedObjectName = pathSplit[0];
    var childrenIds = new Array();
    if (pathSplit.length = 2){
        return deferred.resolve(parentObject.Id);
    }
    else{
        nestedObject = parentObject[nestedObjectName];
        pathSplit.shift();
        var promises = [];
        for (child in nestedObjects.children){                      //iteration
            promises.push(
                asyncCalltoGetDetails(child).then{ //After this line, the promises array resolves. !?!?!
                    getChildren(pathSplit, child).then(function(childId){   //recursivity
                        childrenIds.push(childId);
                    });     
                }           
            );
        }
        JQuery.when.apply(null, promises).then(function(){
            return deferred.resolve(childrenIds);
        });
    }
    return deferred.promise();
}

When I make an iteration using an async call I use promises[] as explained here: How do you work with an array of jQuery Deferreds?

And when I use a recursive call using an async method I used a deferred object pass all the through way. As explained here: AngularJS, promise with recursive function

The problem I have is that promises resolve when the asyncCalltoGetDetails is made, but I want to resolve it when the recursive getChildren return the deferred.resolve();

Any idea what I'm doing wrong? How to use properly the technique of promises[] and deferred object iterated in the same method?

Thanks for your time!

Était-ce utile?

La solution

The problem I have is that promises resolve when the asyncCalltoGetDetails is made, but I want to resolve it when the recursive getChildren return the deferred.resolve();

You're abusing the deferred a little, but it should work. If the promise resolves before asyncCalltoGetDetails has done its work, you need to search for the error in that function.

Any idea what I'm doing wrong?

It might be only your pseudocode, but this looks buggy:

promises.push(
    asyncCalltoGetDetails(child).then{ //After this line, the promises array resolves. !?!?!
        getChildren(pathSplit, child).then(function(childId){   //recursivity
            childrenIds.push(childId);
        });     
    }           
);

then does expect a function, so I guess you gave it a function expression. Which line did you mean then - the then executing but not its callback, the callback executing but not waiting for getChildren?

For the latter the solution is that then, when used for chaining of action (composing promise plus callback to a new promise) allows you to return a promise from the callback. That's what's missing here - the return statement! If you just call getChildren, its result will never be used anywhere, the callback just returns undefined.


Also, for properly using promises, this is ugly:

    JQuery.when.apply(null, promises).then(function(){
        return deferred.resolve(childrenIds);
    });
}
return deferred.promise();

Stop using the "helper" array childrenIds (from the async callbacks)! Stop creating that deferred manually - you're not even rejecting it! Instead, make the children ids the result values of the promises, and use the arguments of your then-callbacks only.

Check my answers to Understanding promises in node.js for recursive function and Is there an example of using raw Q promise library with node to recursively traverse a directory asynchronously? - even though they're not using jQuery's implementation, they should give you an idea of how to do it.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top