Reputation: 392
Hi I want to execute a batch of ajax calls and get the response and then render the results for the user.
I'm using this code but it is not working because the render function executes before all the ajax responses have been collected.
serviceQuery: function (id) {
return $.getJSON(SERVICEURL + "/", id);
},
queryService: function(data){
var self = this;
var queries = [];
var results = [];
$.each(data, function (index, value) {
queries.push(self.serviceQuery(value.id));
});
$.when(queries).done(function (response) {
$.each(response, function (index,val) {
val.then(function (result){
results.push(result[0]);
});
});
self.renderResult(results);
});
},
renderResult: function(results){
$.each(results, function (index, value) {
///Error here cause the value.Name is undefined
console.info(value.name);
});
}
Any Idea on how to wait for all the ajax calls to finish before execute the render function?
Upvotes: 0
Views: 953
Reputation: 1
Use .apply()
at $.when()
call to handle an array of Promise
s. Note also that .then()
returns results asynchronously
let queries = [
// `$.ajax()` call and response
new $.Deferred(function(dfd) {
setTimeout(dfd.resolve, Math.floor(Math.random() * 1000)
// response, textStatus, jqxhr
, [{name:"a"}, "success", {}])
})
// `$.ajax()` call and response
, new $.Deferred(function(dfd) {
setTimeout(dfd.resolve, Math.floor(Math.random() * 1000)
// response, textStatus, jqxhr
, [{name:"b"}, "success", {}])
})
];
$.when.apply(null, queries)
.then(function() {
renderResult($.map(arguments, function(res) {return res[0]}));
});
function renderResult(results) {
$.each(results, function (index, value) {
console.info(value.name);
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
Upvotes: 2
Reputation: 8274
I see one potential issue here:
$.when(queries).done(function (response) {
$.each(response, function (index,val) {
val.then(function (result){
results.push(result[0]);
});
});
self.renderResult(results);
});
Basically, your pseudocode says this:
For each return value from your $.when() command, take the value of that and return a new promise (via val.then
). However, because you never wait for the val deferred to run, results.push
is not guaranteed to be called before your self.renderResult(results)
call.
The code looks weird to me in that you would need two nested deferreds for an ajax call. So I think a larger meta issue is why do you need to do val.then
in the first place. However, given the current code, you would need to do something like this:
var innerDeferreds = [];
$.each(response, function (index,val) {
innerDeferreds.push(val.then(function (result){
results.push(result[0]);
}));;
});
$.when(innerDeferreds).then(function() { self.renderResult(results); });
Again, my guess is that you don't need the val.then
in the first place, but I would need to look in a debugger to see what the values of response
, index
and val
are. (If you set up a jsfiddle that would be super helpful!)
Upvotes: 0
Reputation: 590
Change the $.each
to a for
loop. It is possible that the .then
on the value isn't finished processing before the loop completes. $.each
is synchronous but the .then
generally, means it's a promise and isn't synchronous.
$.each(response, function (index,val) {
val.then(function (result){
results.push(result[0]);
});
});
Change too
for(var idx = 0; idx < response.length; idx++) {
results.push(response[idx]);
}
or keeping with the each
you may just need to remove the .then
call.
$.each(response, function (index,val) {
results.push(val[0]);
});
Upvotes: 0