最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to set new properties, or push to array with async and await, within callback function? - Stack Overflow

programmeradmin7浏览0评论

When I use async/await with rawCollection and get data inside a loop, and then set new properties (poTmp), it works as expected. But after I set new properties and console.log outside it doesn't set new props. Why?

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

When I use async/await with rawCollection and get data inside a loop, and then set new properties (poTmp), it works as expected. But after I set new properties and console.log outside it doesn't set new props. Why?

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
Share Improve this question edited Jun 4, 2020 at 10:54 insipidlight 172 silver badges5 bronze badges asked Jul 3, 2018 at 14:50 phan chanraphan chanra 691 silver badge9 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

The issue is here:

data.forEach(async item => {

async functions return promises immediately when invoked, so the forEach pletes and moves on to the console.log line.

The async work delegated to the async functions has not yet pleted at this point and so the data is not yet modified.

Since it seems you are already in an async function (since you've used await higher in the code), you can wait for all the promises to resolve with await and Promise.all

Promise.all expects an array of promises, so instead of forEach we can use map to create an array of promises

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

Like forEach, map will iterate over all of the items and run the given function. Unlike forEach, map will return an array with the results of these functions, and given they are async functions, each one will return a promise.

Now we use Promise.all to create a single promise that will resolve when every one of the async functions have finished. And we use await to tell the function to pause until that new promise resolves.

Pausing the function with await means the console.log won't run until every one of those async functions have finished, meaning it will have the correct data when it does run.

Here is a working example anyone who needs it:

  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');
            }

        })
        );

  }

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论