簡體   English   中英

for...of、await...of 和 Promise.all 中的 Javascript 異步/等待執行順序問題

[英]Javascript async/await execution order problem in for...of, for await...of and Promise.all

對於數組(產品)中的每個對象(產品),我從貓鼬數據庫中獲取價格。 該值 (prodDB.price) 與循環前初始化為 0 的“amount”變量相加。

我嘗試了其他問題中解釋的 3 個解決方案,其中包括:

  • 對於的
  • 等待
  • 承諾.all

--- 對於 ---

 let amount = 0;
     
 for (const product of products) {
     await Product.findById(product._id).exec((err, prodDB)=> {
         amount += product.count * prodDB.price;
         console.log("Current amount", amount);
     });
 };
 console.log("Amount total", amount);

--- 等待 ---

 let amount = 0;
     
 for await (const product of products) {
     Product.findById(product._id).exec((err, prodDB)=> {
         amount += product.count * prodDB.price;
         console.log("Current amount", amount);
     });
 };
 console.log("Amount total", amount);

--- Promise.all ---

let amount = 0;

await Promise.all(products.map(async (product)=> {
    await Product.findById(product._id).exec((err, prodDB)=> {
    amount += product.count * prodDB.price;
    console.log("Current amount", amount);
    });
}));

 console.log("Amount total", amount);

任何以前版本的代碼的結果總是相同的,而且是出乎意料的,尤其是 console.log 發生的順序:

Amount total 0
Current amount 10.29
Current amount 17.15
Current amount 18.29
Current amount 19.45
Current amount 43.2

你能幫忙嗎? 非常感謝!

問題是你混合了“回調”模式和“等待”模式。 要么await操作,要么給它一個回調,否則它會變得混亂。

for (const product of products) {
    let prodDB = await Product.findById(product._id).lean().exec(); // add lean() to get only JSON data, lighter and faster
    amount += product.count * prodDB.price;
    console.log("Current amount", amount);
};

但是,這是非常昂貴的,因為如果您有 10 個產品,您將調用您的數據庫 10 次。 最好只調用一次並一次性獲取所有 _id。

let allIds = products.map(p => p._id),
    prodDBs = await Product.find({
        _id: {
            $in: allIds
        }
    })
    .lean()
    .exec()

const amount = prodDBs.reduce((a,b) => a.price + b.price, 0)

我會使用Promise.all以便您可以並行運行所有數據庫請求並等待所有請求完成,而不是Promise.all運行所有請求。 我認為唯一的問題是.exec()不返回Promise ,只需使用返回Promise findById() ,試試這個代碼:

let amount = 0;

await Promise.all(products.map(async (product)=> {
  const prodDB = await Product.findById(product._id)
  amount += product.count * prodDB.price
}));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM