2016-11-03 32 views
0

我正在使用NodeJS後端服務,並使用promise來加載任何數據。現在,我想對來自不同來源的項目進行組合(數組)。我有以下解決方案,但我不認爲這是解決此類問題的正確方法。在循環(節點)中使用promises

var results = []; 
loop(items, index, data, results).then(function() { 
    console.log(results); 
}); 

function loop(items, index, data, results) { 
    return utils.getPromise(function(resolve, reject) { 
     if (index === items.length) { 
      // Stop 
      resolve(); 
     } else { 
      doAction(items[index], data).then(function(result) { 
       if (result) { 
        mergeResults(results, result) 
       } else { 
        loop(items, index + 1, data, results).then(resolve, reject); 
       } 
      }, reject); 
     } 
    }); 
} 

function doAction(item, data) { 
    return utils.getPromise(function(resolve, reject) { 
     item.doIt(data).then(resolve, reject); 
    }); 
} 

我認爲正確的方法是立即返回一個承諾,並在飛行中添加的結果,但我不知道究竟如何做到這一點。有什麼建議麼?

回答

4

您可以使用Promise.all收集承諾中的所有結果。 .all承諾本身然後解析一個數組包含每個承諾的所有單一結果。

我認爲正確的方法是像你建議,你將只返回的承諾,並創建這些承諾的陣列返回一個承諾立即

。循環後,您將此數組轉換爲Promise.all

可能是這樣的:

var promiseArray = []; 
for(var i=0;i<array.length;i++){ 
    promiseArray.push(doSomethingAsync(array[i])); 
} 
Promise.all(promiseArray).then(function(responseArray){ 
    //do something with the results 
}); 
1

function randTimeout(t) { 
 
    return new Promise(function (resolve) { 
 
    setTimeout(function() { 
 
     console.log('time done:' + t); 
 
     resolve(); 
 
    }, t); 
 
    }); 
 
} 
 

 
var timeouts = []; 
 
for (var l = 0; l < 20; l ++) { 
 
    timeouts.push(Math.random() * 1000 | 0); 
 
} 
 

 
console.log('start'); 
 
Promise.map(timeouts, function (t) { 
 
    return randTimeout(t); 
 
}, {concurrency: 3});
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.4.6/bluebird.min.js"></script>

像@Tobi說,你可以使用Promise.All ..

但Promise.all有一個疑難雜症! !

如果你的處理包含很多項目的數組,發送大量項目去同時做一些異步工作可能是次優的。並且在某些情況下不可能,例如。在節點中一次打開太多文件會給你帶來太多的句柄錯誤。

藍鳥承諾庫有一個稱爲map的有用函數,並且有一個選項叫concurrency。這允許您一次處理X個承諾。就我個人而言,我認爲具有併發選項的map函數應該是Promise規範的一部分,因爲它非常有用。如果不使用併發選項,它將與promise.all具有相同的效果,而不必先創建數組。

在上面的例子中,我創建了20個隨機超時,最大1秒。如果不使用映射,最大時間將會是1秒,因爲所有的承諾都會一次執行。但是使用3的併發選項,它一次只能執行3個,正如你所看到的,完成時間超過1秒。