2016-05-31 31 views
2

我已經認識到,由於ECMAScript 6中的承諾允許對異步函數進行同步編碼,因此對於每一個有承諾的代碼段,都有一個同步推論。例如:「while」循環的Promise版本?

var data = processData(JSON.parse(readFile(getFileName()))); 

是一樣的:

var data = getFileName() 
    .then(readFile) 
    .then(JSON.parse) 
    .then(processData); 

現在對於我現在的用例,我想寫代碼從一個大規模的公共API中提取數據。該API進行分頁,所以在純同步世界我會寫類似如下:

var data = []; 
var offset = 0; 
var total = 10000; // For example - not actually how this would work 
while(offset < total) { 
    data.concat(getDataFromAPI(offset)); 
    offset = data.length; 
} 

現在的問題是,我將如何做到這一點與承諾?我可以寫這樣的:

var data = []; 
var offset = 0; 
var total = 10000; 
getDataFromAPI(offset) 
    .then(function(newData){ 
     data.concat(newData); 
     return getDataFromAPI(data.length); 
    }); 

但在這一點上,我不得不公正連鎖無限.then秒 - 沒有循環邏輯。我覺得應該可以使用遞歸,但我不知道如何去做。

我使用BluebirdJS作爲我的承諾庫,所以我可以訪問他們所有的輔助方法。

+0

怎麼樣遞歸自調用匿名函數(最終與Promises結合)呢?這裏只是一個例子:https://jsfiddle.net/f5ud8ytx/。用你自己的api調用替換超時,並使用api調用返回的promise的.then再次調用該函數,直到結束達到0(當前 - 執行直到結束高於0) – briosheje

+0

你可以用'異步each' – r3wt

回答

6

我覺得應該的東西使用遞歸

究竟是不可能的。您可以命名回調,以便您可以再次參考。只要條件不滿足,就從回調中返回一個承諾。否則返回最終結果:

getDataFromAPI(offset) 
    .then(function next(newData){ 
    data.concat(newData); 
    var newOffset = data.length; 
    return newOffset < total ? getDataFromAPI(newOffset).then(next) : data; 
    }) 
    .then(function(data) { 
    console.log(data); // final result 
    });