2017-06-13 66 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/