I am trying to use deferred and promises within the context of a loop and I fail doing so.
I need to call a first method asynchronously. This first method (let´s call it getArray()) returns an array.
For each element of the array, I need to call a second method, let´s call it getData(id). The id is stored in the array returned by getArray.
Finally, once I have the result of getData(), I need to use the result to call a third method, let´s call it getDetails().
Once all the calls are done and the loop is finished, I need to return the array, with extra data and details.
I created a jsfiddle: http://jsfiddle.net/chevdor/953sLkts/
var myarray = [];
var log = function(s){
$('#console').append('<p>'+s+'</p>');
};
var get1 = function() {
var dfd = jQuery.Deferred();
log('Running get1');
setTimeout(function() {
var res = [1, 2, 3, 4];
// that´s probably crap...
for (var i= 0; i< res.length; i++){
get2(res[i])
.done(get3(res[i])
.done(get4(res[i]))
);
}
dfd.resolve(res);
}, Math.floor(400 + Math.random() * 1000));
return dfd.promise();
};
var get2 = function(index) {
var dfd = jQuery.Deferred();
log('Running get2');
setTimeout(function() {
var res = {
index: index,
val: index * 2
};
myarray[index]= res;
dfd.resolve(res);
}, Math.floor(400 + Math.random() * 1000));
return dfd.promise();
};
var get3 = function(index) {
var dfd = jQuery.Deferred();
log('Running get3');
setTimeout(function() {
var res = {
index: index,
val2: index * index
};
myarray[index].extra = res;
dfd.resolve(res);
}, Math.floor(400 + Math.random() * 1000));
return dfd.promise();
};
var get4 = function(index) {
var dfd = jQuery.Deferred();
log('Running get4');
setTimeout(function() { // Resolve after a random interval
var res = {
index: index,
val2: index * index
};
dfd.resolve(res);
}, Math.floor(400 + Math.random() * 1000));
return dfd.promise();
};
log('start');
get1();
to illustrate. It definitely does not work and look ugly...
Can you explain what would be the proper way to do that?
May I introduce you to $.when.
From your code, it looks like your get2(), get3(), get4() are the getData(), getDetail(). Assume they all are made like a promise. Then you can do this:
I was a big fan of bluebird promise, the keyword was .all() instead of .when(). I am not exactly sure how jquery promise work, but I believe it is a very similar structure. Hope this helps. Let me know if it is unclear :)
EDIT: Sorry for the confusion, to use $.when on array of promises, the syntax is:
Note the "data" here is only the resolved from promise1, I am not familiar with jquery. But I do recommend bluebird promise. Which is faster and cleaner.