尽管我读过很多帖子,但我有点困惑......
我想将N
AJAX请求链接到N >= 1
。 N
取决于第一个请求的响应,第一个请求和剩余请求之间存在依赖关系。我不想冻结浏览器。
由于用例有点复杂,我会尽量简化。想象一下,我们有一个API可以检索应用程序的所有用户和每个用户的个人地址。我想显示所有地址。像这样:
function doSomething() {
var addresses = '';
$.getJSON('/api/users', function(data) {
$(data).each(function(id, user) {
$.getJSON('/api/user/' + user.id + '/address', function(address) {
addresses += address.displayName + '<br/>';
});
});
});
// do something with the addresses and display it somewhere
$("#xxx").append(addresses);
}
最好的方法是什么?
答案 0 :(得分:3)
以这种方式使用complete
变量:
function doSomething() {
var addresses = '';
$.getJSON('/api/users', function(data) {
var complete = 0;
$(data).each(function(id, user) {
$.getJSON('/api/user/' + user.id + '/address', function(address) {
addresses += address.displayName + '<br/>';
if (++complete !== data.length) { return; }
// do something with the addresses and display it somewhere
$("#xxx").append(addresses);
});
});
});
}
此外,使用promises是另一种解决方案:
function doSomething() {
var addresses = '';
$.getJSON('/api/users', function(data) {
var $allAjax = [];
$(data).each(function(id, user) {
$allAjax.push($.getJSON('/api/user/' + user.id + '/address', function(address) {
addresses += address.displayName + '<br/>';
}));
});
$.when.apply($, $allAjax).done(function () {
// do something with the addresses and display it somewhere
$("#xxx").append(addresses);
});
});
}
要保持地址顺序,您应该使用数组:
var addresses = [];
而不是+= address.displayName + "<br/>"
,你会这样做:
addresses[id] = address.displayName;
最后只需覆盖addresses
变量:
addresses = addresses.join("<br/>");
答案 1 :(得分:0)
您可能会发现重构代码以提供getAddresses()
函数更有用,它可以实现这一点 - 获取地址。该函数需要返回一个promise。
function getAddresses() {
return $.getJSON('/api/users').then(function(data) {
return $.when.appy(null, data.map(function(user) {
return $.getJSON('/api/user/' + user.id + '/address');
})).then(function () {
//convert the function's arguments to an array of addresses
return Array.prototype.slice.apply(arguments).map(function(a) {
return a[0];//crazy but that's the way jQuery's ajax functions deliver their data
});
});
});
}
现在,在调用getAddresses()
的地方,可以使用地址执行某些操作:
var promiseOfAddresses = getAddresses().then(function(addresses) {
// do something with the addresses and display it somewhere
var displayNames = addresses.map(function(address) {
return address.displayName;
});
$("#xxx").append(displayNames.join('<br/>'));
return addresses;
});
promiseOfAddresses =
分配对于回答问题并不是绝对必要的,但如果您需要对代码中的地址进行其他任何操作,这将非常有用。
promiseOfAddresses.then(function(addresses) {
//do something else with the addresses here
});