以特定顺序调用嵌套的AJAX调用
我试过通过this question和this,但我似乎无法弄清楚如何使我的需求工作。我想在循环中多次调用https://reqres.in/api/users。此AJAX调用仅返回虚拟用户的第一页。在收到第一页后,我想打电话给下一页。以特定顺序调用嵌套的AJAX调用
这里是我的代码:
$(document).ready(function() {
function getMoreUsers() {
var def = $.Deferred();
var requests = [];
for (var j=2; j<=4; j++) {
console.log("getting info for page # " + j);
requests.push(
$.ajax("https://reqres.in/api/users?page=" + j).done(function() {
console.log("got info for page # " + j);
def.resolve();
})
);
}
return def.promise();
}
function getAllUsers() {
var def = $.Deferred();
var requests = [];
for (var i=0; i< 2; i++) {
console.log("iteration # " + i);
requests.push(
$.ajax("https://reqres.in/api/users").done(function(data) {
console.log("got first page info");
getMoreUsers();
def.resolve();
})
);
}
return def.promise();
}
getAllUsers().done(function() {
console.log("all completed");
});
});
,我得到的输出是这样的:
iteration # 0
iteration # 1
got first page info
getting info for page # 2
getting info for page # 3
getting info for page # 4
all completed
got first page info
getting info for page # 2
getting info for page # 3
getting info for page # 4
got info for page # 5
不过,我想这样的:
iteration # 0
got first page info
getting info for page # 2
got info for page # 2
getting info for page # 3
got info for page # 3
getting info for page # 4
got info for page # 4
iteration # 1
got first page info
getting info for page # 2
got info for page # 2
getting info for page # 3
got info for page # 3
getting info for page # 4
got info for page # 4
all completed
我甚至不知道如何page # 5
当我循环到4时出现在输出中,它出现了6次,如下所示:
为什么不保持简单?
var getUsers = function(i) {
$.ajax("https://reqres.in/api/users?page=" + i).done(function() {
if (i < 5) {
getUsers(i + 1);
}else{
//done!
}
});
}
getUsers(1);
更新:
感谢,递归似乎工作,但如果我附上()完成对getUsers()像这样 - getUsers(1).done(函数( ){console.log(“all done”);});它不会着火。我不明白。我认为$ .ajax()自己返回一个延迟对象。
我的代码只是一个提示你如何解决你的问题。反正让我帮你进一步。
有简单的方法:
$.ajax("https://reqres.in/api/users?page=" + i).done(function() {
// use data, store it in array outside or draw HTML
if (i < 5) {
getUsers(i + 1);
}else{
//done! do something when finished
// iAmDoneHere()
}
});
,但如果你想使用延迟:所以$.ajax
回报的递延。递归运作良好,但我想你想exensule最终“下载所有!”功能。在这种情况下,您需要稍微改进代码。
var pages = [];
var getUsers = function(maxPage, currentPage, deferred) {
var deferred = false;
if (!currentPage) {
// this is the top function call
// the top call without recursion
var currentPage = 1;
deferred = $.Deferred();
}
$.ajax(..."?page="+currentPage).done(function(){
// we got page info, great! what next?
pages.push({insert the page data here});
// what next?
// if there is more to fetch, do it
if (i < maxPage) {
// pass maxPage, page to parse + 1 and top deferred
var subd = getUsers(maxPage, i + 1, deferred);
}else{
// if there is more to parse, do it
// we downloaded the final page
// so now we can finally resolve the top deferred
// which was passed in every recursion
deferred.resolve();
}
}
return deferred;
}
getUsers(10).done(function(){
// executed when all pages are done
// results are stored in pages[]
});
最糟糕的是我已经写了很多,这仍然有待改进(我应该pages[]
变量作为全球/父范围)
我想说的管理异步回调是很容易的,但它更先进的,做一个简单的回调。
,如果你在你propably编写或使用一些类,将尽一切的为你而不用担心任何事情,例如
var getUsers = function(maxPages) {
var d = $.Deferred();
var pages = [];
var queue = new Queue();
for (var i=0;i<maxPages;i++) {
queue.push(function(page){
return $.ajax(.."?page="+page).done(function(){pages.push(page);});
}, i);
}
queue.run(function(){
d.resolve(pages);
});
return d;
}
getUsers(10).done(function(pages){/* all pages in "pages" */});
这样做是正确的方式,你赢得了更大的项目工作如果您想在其他地方使用队列,请不要重复您的代码。也有很多强麦准备NPM包在那里
也是我必须要提到,我可以看到你真的要坚持推迟白色很多人只是用callbacks
代替deferred
或promises
简单的任务。
// Deferred way
function doJob(arg1, arg2) {
var d = $.Deferred();
window.setTimeout(function(){
d.resolve();
}, 100);
return d;
}
// Callback way
function doJob(arg1, arg2, callback) {
window.setTimeout(function(){
callback();
}, 100);
}
它节省了一点代码和复杂性,但为开发人员提供了更少的层次和选项。这两种方法都很好。我在说所有这些让你知道有很多方法,没有定义答案如何回答你的问题。
我会去一些队列,回调的解决方案是最简单的,延迟/ Promise +递归解决方案是好的。
谢谢,递归似乎工作,但如果我像''getUsers(1).done(function(){console.log(“all done”))一样将'done()'附加到'getUsers()' });'它不会触发。我不明白。我认为'$ .ajax()'自己返回了一个延迟对象。 –
@SidharthSamant看到我的更新 – Peter
在你不需要的递延第二吼声。递归更好。
$(document).ready(function() {
var apiUrl = "https://reqres.in/api/users";
var baseAjaxConfig = {
method: "GET",
url: apiUrl
};
var page = 1;
var maxUsers = 5; //CHANGE THIS ACCORDING TO WHAT YOU WANT
function getUser(page) {
var ajaxConfig = $.extend({}, baseAjaxConfig, {data: {page: page}});
$.ajax(ajaxConfig).done(function() {
(page < maxUsers) && getUser(page+1);
}).fail(function() {
(page < maxUsers) && getUser(page+1);
});
}
getUser(page);
});
这里有一个小提琴==>https://jsfiddle.net/tonysamperi/5j8166be/
jQuery.Deferred()是你需要的 –
我已经使用过它,但不正确,我猜。 –
首先,您不需要创建新的延迟对象,解析并为每个AJAX请求返回它。 '$ .ajax'方法本身返回一个延迟对象:) – Terry