如何设置新属性或使用异步函数推送到数组并在回调函数中等待?

时间:2018-07-03 14:50:36

标签: javascript meteor vue.js

这是我的脚本,我不知道为什么当我在循环中获取数据然后在我的数据中设置新属性(poTmp)时在rawCollection中使用asysc await和rawCollection,但是在设置新属性后我会在其外部进行控制台不设置新道具为什么?

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

2 个答案:

答案 0 :(得分:1)

问题在这里:

data.forEach(async item => {

异步函数在调用后立即返回promise,因此forEach完成并移至console.log行。

委托给异步功能的异步工作目前尚未完成,因此数据尚未修改。

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

Promise.all期望一个承诺数组,因此我们可以使用forEach来创建一个承诺数组,而不是map

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

forEach一样,map将遍历所有项目并运行给定的函数。与forEach不同,map将返回一个包含这些函数结果的数组,并且鉴于它们是异步函数,每个函数都会返回一个promise。

现在,我们使用Promise.all来创建一个诺言,该诺言将在每个异步函数完成时解决。然后,我们使用await告诉函数暂停,直到新的承诺解决为止。

await暂停功能意味着console.log在所有异步功能都完成之前不会运行,这意味着它在运行时将具有正确的数据。

答案 1 :(得分: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');
            }

        })
        );

  }