问题
Reading a JSON-Service like this:
$.ajax({
url:'activeIDs',
success : function(data){ // data = [14,15]
var tableRows = [];
for (var dataIndex=0; dataIndex < data.length; dataIndex++) {
var isLast = dataIndex == (data.length - 1);
$.ajax({
url: 'info?id=' + data[dataIndex],
success: function(data2) { // "foo", "bar"
tableRows.push(data2.name);
if (isLast) {
alert(tableRows.length);
}
}
});
}
}
});
First network-trace is:
- activeIDs =
[14,15]
- info?id=14 (takes 2 seconds) =
"foo"
- info?id=15 (takes 4 seconds) =
"bar"
In this case the alert gives "2".
Seconds network-trace is different:
- activeIDs =
[14,15]
; - info?id=14 (takes 20 seconds) =
"foo"
(now takes very long) - info?id=15 (takes 1 second) =
"bar"
In this case the alert gives 1
after one second, this is bad!!!
Question:
How to use $.Deferred instead of isLast
?
回答1:
You'll need to wait for all requests to finish before alert
ing.
$.ajax({
url:'activeIDs',
success : function(data){ // data = [14,15]
var tableRows = [];
var requests = [];
for (var dataIndex=0; dataIndex < data.length; dataIndex++) {
var isLast = dataIndex == data.length;
var request = $.ajax({
url: 'info?id=' + data[dataIndex]
}).done(function(data2) { // "foo", "bar"
tableRows.push(data2.name);
});
requests.push(request);
}
// wait for all requests to finish here
$.when(requests).then(function(){
// all success functions have been called and updated things appropriately
alert(tableRows.length);
}
}
});
This assumes that all requests succeed. It also looks like there are a few typos
- Where does
tableRows
get updated? - Where is
entries
defined?
Edit
Now using promise style success handler. Should push the result in to tableRows
before calling the $.when().then
callback
回答2:
Why do you want $.Deferred ? Your $.ajax calls are returning a promise, so, you can use it:
var promisesArray = [];
for (var dataIndex=0; dataIndex < data.length; dataIndex++) {
promisesArray.push($.ajax({...}));
}
$.when.apply($, promisesArray).then(...);
(inspired by this answer)
You can use deferreds by taking this solution and passing it to a deferred if you want, but it's not neccesary:
var x = $.Deferred(function(defer){
var promisesArray = [];
for (var dataIndex=0; dataIndex < data.length; dataIndex++) {
promisesArray.push($.ajax({...}));
}
$.when.apply($, promisesArray).done(function(data) { defer.resolve(data); });
});
return x.promise();
(Not tested, I'm sorry)
回答3:
Use jQuery when
// Function to return id info based on this example http://stackoverflow.com/questions/5316697/jquery-return-data-after-ajax-call-success
function getInfo(ID) {
return $.get("info?id=" + ID);
}
// based on examples from https://api.jquery.com/jQuery.when/
var promises = [];
var jqxhr = $.get("activeIDs")
.done(function(data) {
$.each(data,function(i,v) {
promises.push(getInfo(v));
});
$.when(promises).done(function(p) {
console.log(p,p.length);
});
})
.fail(function() {
alert( "Error" );
});
来源:https://stackoverflow.com/questions/37047280/deferred-and-ajax