2017-06-13 61 views
1

我试过通过this questionthis,但我似乎无法弄清楚如何使我的需求工作。我想在循环中多次调用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次,如下所示:

enter image description here

+0

jQuery.Deferred()是你需要的 –

+0

我已经使用过它,但不正确,我猜。 –

+0

首先,您不需要创建新的延迟对象,解析并为每个AJAX请求返回它。 '$ .ajax'方法本身返回一个延迟对象:) – Terry

回答

1

为什么不保持简单?

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代替deferredpromises简单的任务。

// 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 +递归解决方案是好的。

+0

谢谢,递归似乎工作,但如果我像''getUsers(1).done(function(){console.log(“all done”))一样将'done()'附加到'getUsers()' });'它不会触发。我不明白。我认为'$ .ajax()'自己返回了一个延迟对象。 –

+1

@SidharthSamant看到我的更新 – Peter

1

在你不需要的递延第二吼声。递归更好。

  $(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/