想象一下,你有一個異步的過程,是n個異步步驟的級聯:爲什麼這個map減少Promises數組不起作用,但只是減少它呢?
function step1(item){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('step 1 fort item ' + item);
});
});
}
function step2(item){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('step 2 for item ' + item);
},1000);
});
}
function step3(item){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('step 3 for item ' + item);
},1000);
});
}
function processItem(item){
let steps = [step1, step2, step3];
return steps.reduce((current, next) => {
return current.then(res => {
console.log(res);
return next(item);
}).then(res => {
console.log(res);
});
},Promise.resolve());
}
所以,現在你有一個項目數組,並且要處理應用功能processItem他們每個人的所有項目。但是爲了限制,所有的流程必須按順序執行,一個流程在前一個流程完成時開始。
好,如果我實現它以這樣的方式
let items = [1, 2, 3];
items.map(i => processItem(i)).reduce((p, next) => {
return p.then(() => {
return next;
});
}).then(() => {
// all finished
});
你得到這樣的輸出:
step 1 for item 1
step 1 for item 2
step 1 for item 3
step 2 for item 1
step 2 for item 2
step 2 for item 3
step 3 for item 1
step 3 for item 2
step 3 for item 3
,只需要3秒,沒有9預期。
同時,如果你實現它避免了地圖的步驟,你會得到預期的結果:
let items = [1, 2, 3];
items.reduce((promise, nextItem) => {
return promise.then(() => {
return processItem(nextItem);
});
}, Promise.resolve()).then(() => {
// all finished
});
結果:
step 1 for item 1
step 2 for item 1
step 3 for item 1
step 1 for item 2
step 2 for item 2
step 3 for item 2
step 1 for item 3
step 2 for item 3
step 3 for item 3
,並採取9秒的預期。
爲什麼會發生這種情況?我認爲,當你將一個promise返回函數映射到一個數組時,你會得到一個promise數組,因此,reduce匿名函數的第一個和第二個參數就是承諾,你可以像我在上面的第一個例子中那樣行事。我有點困惑。
在你的'.map'例子中,你會立即調用'processItem'每個'i'無需等待每完成和分配方法的返回值到_Array_中的項目,所以是的,你有一個_Array_的_Promises_,但是這些promise中的每一個都沒有鏈接,在'.reduce'的例子中,你設置了一個單鏈_Promises_ –
@PaulS。那麼,如果不立即調用processItem函數,映射到每個數組項的最佳方法是什麼? – jgldev