我正在閱讀“Eloquent JavaScript”,在異步章節的末尾有一節關于異步操作中的執行間隙,它顯示了一個示例。本書下面的示例代碼不可運行,因為它使用了一些虛構的場景。
function anyStorage(nest, source, name) {
if (source == nest.name) return storage(nest, name); else return routeRequest(nest, source, "storage", name);
}
async function chicks(nest, year) {
let list = "";
await Promise.all(network(nest).map(async name => {
list = `${name}: ${
await anyStorage(nest, name, `chicks in ${year}`)
}\n`; }));
return list;
}
它說這個代碼的問題,據我所知,每個異步呼叫例如anyStorage實際上會連接一個空list并且看不到來自其他異步呼叫的突變。
我試圖復制這個問題如下:
function delay(n) {
return Promise.resolve(setTimeout(()=>{}, n*1000));
}
async function asyncSum(a) {
let sum = 0;
await Promise.all(a.map(async i => sum = await delay(i)));
return sum;
}
asyncSum([1,2,3,4]).then(value => console.log(value));
但這按預期作業。它正確列印總和。那么是我誤解了這本書還是我的例子有問題?
uj5u.com熱心網友回復:
原始代碼中的問題在于:
list = `${name}: ${ await ...
list =就像在做-list = list 但第二個串列:
list = list
^^^^
指list 在那一刻- 在任何異步呼叫完成之前。最終,其中一個將完成并分配給list. 但是一旦下一個決議,因為list它參考的是原始的,而不是新更新的,之前的結果將丟失。
這是一個演示:
const getMultipliedNum = num => Promise.resolve(num * 3);
(async() => {
let list = "";
await Promise.all([1, 2, 3].map(async num => {
list = `${num}: ${ await getMultipliedNum(num)}\n`;
}));
console.log(list);
})();
您的示例有同樣的問題,盡管delay函式已損壞 - 結果為 4,這只是最終setTimeout呼叫的結果(因為setTimeout回傳超時 ID)。修復它以演示問題:
function delay(n) {
return Promise.resolve(n);
}
async function asyncSum(a) {
let sum = 0;
await Promise.all(a.map(async i => sum = await delay(i)));
return sum;
}
asyncSum([1,2,3,4]).then(value => console.log(value));
結果是 4,而不是 10 - 這表明sum = await somethingElse并行回圈內部不起作用。
另一種看待它的方式:
sum = await somethingElse
就像在做
const currentValueOfSum = sum;
sum = currentValueOfSum await somethingElse;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/475513.html
標籤:javascript 异步 es6-承诺
