javascript - 如何在回调函数中设置新属性,或使用异步和等待推送到数组?
问题描述
当我将 async/await 与 rawCollection 一起使用并在循环内获取数据,然后设置新属性 (poTmp) 时,它按预期工作。但是在我在外面设置新属性和 console.log 之后,它并没有设置新的道具。为什么?
let items = await Items.rawCollection()
.aggregate([
{
$match: match,
},
])
.toArray()
let data = items
data.forEach(async item => {
let po = await PurchaseOrderDetails.rawCollection()
.aggregate([
{
$match: {
itemId: item._id,
tranDate: { $lte: tDate },
},
},
{
$group: {
_id: '$itemId',
itemDoc: { $last: item },
onHandPO: { $sum: '$qtyBase' },
},
},
{
$group: {
_id: '$itemId',
itemDoc: { $last: '$itemDoc' },
lastOnHandPO: { $last: '$onHandPO' },
},
},
])
.toArray()
//==================
//set new properties
//==================
item.poTmp = po[0]
})
console.log(data)
return data
解决方案
问题在这里:
data.forEach(async item => {
async 函数在调用时立即返回 Promise,因此 forEach 完成并继续执行console.log
。
此时委派给异步函数的异步工作尚未完成,因此尚未修改数据。
由于您似乎已经在一个异步函数中(因为您在代码中使用了更高的 await),您可以等待所有的 Promiseawait
解决Promise.all
Promise.all
需要一个 promise 数组,所以forEach
我们可以使用map
创建一个 promise 数组来代替
await Promise.all( data.map(async item => { ...
Like forEach
,map
将遍历所有项目并运行给定的函数。与, 不同forEach
,map
将返回一个包含这些函数结果的数组,并且鉴于它们是异步函数,每个函数都将返回一个 Promise。
现在我们Promise.all
用来创建一个单一的 Promise,它将在每个异步函数完成时解析。我们await
用来告诉函数暂停,直到新的承诺解决。
暂停函数await
意味着 console.log 在每个异步函数都完成之前不会运行,这意味着它在运行时将拥有正确的数据。
推荐阅读
- tensorflow - 由于 TF2 中的 tfVariable 问题,简单的 RNN 模型无法工作
- java - 如何从 java 代码执行以下命令行表达式?
- sql - 查询“@”之后的所有内容
- node.js - Firebase 管理员:是否有必要检查服务器上解码的 uid(基于客户端 ID 令牌)是否与客户端的 uid 匹配?
- flutter - Flutter ListView 的自定义 Widget 包括 ListView 给出错误
- docker - Terraform docker_container 标签不起作用?
- python - 在 Python 3.7 中设置动态加载模块的路径
- php - Jquery点击功能和ajax代码调用php文件上传图片的问题
- ionic3 - 在 Ionic 3 应用程序中打开外部链接
- logging - Microsoft.Extensions.Logging 与。日志