Reputation: 43
I read a lot of answers about deferred but cannot exactly find what I want.
The close piece of code is http://jsfiddle.net/UZzeC/
Difference in my code is that I want to call on "process" function inside the when. statement N number of times.
//Dynamically generated JSON list
var json_list = [
{"id":"div1","name":"Google.com"},
{"id":"div2","name":"eBay.com"}
{"id":"div3","name":"Yahoo.com"},
{"id":"div4","name":"Facebook.com"}
];
$.when(
for (var i in json_list) {
process(json_list[i].id, json_list[i].name),
}
).done(function() {
$('#global').text("OK"); }
) .fail(function() {
$('#global').text("FAIL");
});
the end state will be the code connecting to multiple web services async and returning its progress when each comes back with data
Can I embed this loop like this? I saw some usage on "Apply" with when but not sure how it would work for me.
Upvotes: 0
Views: 205
Reputation: 19288
Only in very exceptional circumstances (practically, never) should for(var i in arr) {...}
be used to loop through an array. The reason is that an array may have properties other than its numeric array indices, that not even if(arr.hasOwnProperty(i))
will filter out.
For example :
var arr = ['A', 'B', 'C'];
arr.color = 'RED';
Now, loop through arr
with for(var i in arr)
and you will discover A
, B
, C
, and RED
. ie the array's members and its properties.
To be guaranteed to address just the array members, loop with for(var i=0; i<arr.length; i++) {...}
.
So, you can do as follows :
var requests = [];
for(var i=0; i<json_list.length; i++) {
requests.push(process(json_list[i].id, json_list[i].name));
}
$.when.apply(null, requests).then(function() {
$('#global').text("OK");
}, function() {
$('#global').text("FAIL");
});
You can also use the native Array.prototype.map()
or jQuery.map()
to loop through the original array and return a processed array. For compactness, the processed array can be passed anonymously to $.when
, as follows :
$.when.apply(null, $.map(json_list, function(request) {
return process(request.id, request.name);
}).get()).then(function() {
$('#global').text("OK");
}, function() {
$('#global').text("FAIL");
});
Upvotes: 2
Reputation: 1654
I think what you want to do is something like this... (supposing process return a $.Deferred().promise() object)
var requests = [];
for (var i=0; i<json_list.length; i++) {
requests.push(process(json_list[i].id, json_list[i].name));
}
$.when.apply($, requests).then(
function() { $('#global').text("OK"); },
function() { $('#global').text("FAIL"); }
);
EDIT: Edited the code to iterate the array properly. I thought it was an object and used for..in, but you should use this way always ;)
Upvotes: 2
Reputation: 340055
for .. in
on arraysfor
loop for a function parameter - JS doesn't work that waySince your json_list
is an array, you can just use .map
to get a new array of Promises, one for for each entry in the original array:
var requests = json_list.map(function(l) {
return func_returning_promise(l.id, l.name);
});
and then you can use Function.prototype.apply
to pass this array of Promises to $.when
as if they were individual parameters:
$.when.apply($, requests).then(okFunc, failFunc);
Upvotes: 0