1

I have a function:

static async assign( assigned_data, assigned_by ) {
    return new Promise( async ( resolve, reject ) => {
        let orders = [];
        await assigned_data.map( async( data ) => {

            // find each order and update 
            await data.assigned.map( async( order_id ) => {
                await this.findByIdAndUpdate( order_id, {
                    $set: { 
                        current_assigned: { 
                            user: data._id,
                            assigned_by: assigned_by,
                        },
                        last_assigned_at: Date.now(),
                        last_assigned_by: assigned_by,
                    },
                    $addToSet: { 
                        assigned_history: { 
                            user: data._id,
                            assigned_by: assigned_by,
                        } 
                    },
                }, ( error, order ) => {
                    if ( error ) {
                        console.log( 'error', error );
                    }
                    console.log( 'order', order );
                    orders.push( order );
                } );
            } );
        } );
        resolve( orders );
    } );
}

Even console.log( 'order', order ); print out order, but I can not push it to orders array.

But orders array still empty when I use this function.

When I use setTimeout it return extractly what I want.

setTimeout(function() {
          resolve( orders );
        }, 1000);

I don't want to using setTimeout, because I don't known how much time to set (eg. 1000 ms in above code).

Please tell me what wrong with my code. Thanks you very much!

Enesy
  • 259
  • 3
  • 13
  • Don't, under any circumstances, make a promise constructor `async`. – Roamer-1888 Sep 07 '18 at 09:04
  • i think `resolve(orders)` is executed before any data is pushed into orders array via `async` methods. Execute it after data is pushed. As, settimeout will take a time of 1000ms to execute and before this orders are pushed into the array. – Abhishek Kumar Sep 07 '18 at 09:07
  • @AbhishekKumar sorry so what I need to do for my code? – Enesy Sep 07 '18 at 09:36
  • try @seunggabi solution as you have to resolve orders only when data is pushed into the array. – Abhishek Kumar Sep 07 '18 at 09:38
  • @AbhishekKumar I have tried and still get empty – Enesy Sep 07 '18 at 09:59
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Evert Sep 07 '18 at 10:17

2 Answers2

0

I think that, just callback! but, I don't test this. hm..

static async assign(assigned_data, assigned_by) {
    const orders = [];
    return new Promise( async ( resolve, reject ) => {
        assigned_data.map((data, index) => {
            data.assigned.map((order_id) => {
                this.findByIdAndUpdate(order_id, {
                    $set: {
                        current_assigned: {
                            user: data._id,
                            assigned_by: assigned_by,
                        },
                        last_assigned_at: Date.now(),
                        last_assigned_by: assigned_by,
                    },
                    $addToSet: {
                        assigned_history: {
                            user: data._id,
                            assigned_by: assigned_by,
                        }
                    },
                }, 
                (error, order) => {
                    error ? console.log('error', error) : console.log('order', order);
                    orders.push(order);

                    if(index === assigned_data.length-1) {
                        resolve(orders); // just callback
                    }
                });
            });
        });
    });
}

Sorry I don't see loop..

You can this. Javascript Map Array Last Item

seunggabi
  • 1,699
  • 12
  • 12
0

You are making the things complicated. Nesting async await is not a good idea, as it is difficult to debug.

There are several problems. Let's take a look on a working sample.

async function assign(assigned_data) {
  let orders = [];
  orders = await Promise.all(assigned_data.map(async(data) => {
    // find each order and update 
    return await Promise.all(data.map(async(order_id) => {
      return await call();
    }))
  }));
  console.log(orders);
}

async function call() {
  var promise = new Promise(function(resolve, reject) {
    setTimeout(function() {
      console.log('order');
      resolve('order');
    }, 2000);
  });
  return promise;
}

data = assign([
  [1, 2, 3],
  [1, 2, 3]
])

First of all, you need Promise.all to await the Promises formed by map.

Second, your nesting job still contains another array (I assume, thus you use map again). So you still need another Promise.all inside the previous Promise.all. (Please don't do this again for even complicated structure)

Lastly, put the real worker outside your nesting async-await loop.

MT-FreeHK
  • 2,462
  • 1
  • 13
  • 29