如何在回调函数中设置新属性,或者用async和await推送到数组?

问题描述 投票:0回答:2

当我用asyncawait和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
javascript meteor vue.js
2个回答
3
投票

问题就出在这里。

data.forEach(async item => {

async函数在被调用后会立即返回承诺 所以forEach完成后就会继续执行 console.log 行。

此时委托给异步函数的异步工作还没有完成,所以数据还没有被修改。

由于你似乎已经在一个异步函数中了(因为你在代码中使用了更高的 await),你可以等待所有的承诺用 awaitPromise.all

Promise.all 期待一个数组的承诺,所以用了 forEach 我们可以用 map 以创建一个承诺数组

await Promise.all( data.map(async item => { ...

喜欢 forEach, map 将遍历所有的项目并运行给定的函数。与 forEach, map 将返回一个包含这些函数结果的数组,鉴于它们是async函数,每个函数将返回一个承诺。

现在我们使用 Promise.all 来创建一个单一的承诺,这个承诺将在每个异步函数完成后解析。而我们使用 await 来告诉函数暂停,直到新的承诺解决。

暂停函数,用 await 意味着 console.log 不会运行,直到每一个 async 函数完成,这意味着当它运行时,它将有正确的数据。


1
投票

这是一个工作实例,需要的人可以看看。

  public async updateBatch(req:any,res:any){

        body = [1,3,4,5,6]

        var rfinal:number[] = [];

        await Promise.all(body.map(async items=>{

            let newStatus = 'MJ';

                inputParameters = [
                { name: 'PID', dataType: sql.Int, value: items },
                { name: 'Status', dataType: sql.VarChar, value: newStatus }
            ];

            let CustomQuery = `UPDATE MYTable 
                SET Status= @Status
                WHERE PID= @PID`;

            const result = await provider.executeQuery(CustomQuery, inputParameters).catch(err => {
                    LogErrors.logErrors(err);
            });
            if(result.rowsAffected[0]>0){
                    rfinal.push(result.rowsAffected[0]);
            }else{
                throw new console.error('Un expected error, updating newsfeed');
            }

        })
        );

  }
© www.soinside.com 2019 - 2024. All rights reserved.