0

I have the following code for my post request in Express:

app.post('/', urlencodedParser, (req, res) => {
    let value = req.body.value;

    let result = data.map(async (currentObject) => {
        return {
            nodeName: currentObject.nodeName,
            nodeStatus: await lib.checkValue(currentObject.nodeUrl, 
currentObject.nodeName, value)
        };
    });
    console.log(Promise.all(result));

    res.render('list', {data:data, value:value});
})

I pass the function to map asynchronously. Then I use Promise.all to get the result when all the promises return.

However, Promise.all itself returns a promise Promise { [ Promise { <pending> }, Promise { <pending> } ] }

Without async, it returns the object [ { nodeName: currentObject.nodeName, nodeStatus: Promise { <pending> }} ]. I'd like to await when my function returns and get the nodeStatus.

Why is this happening? Am I missing something?

Len
  • 11
  • 1
  • 2
  • await Promise.all(result), async (req, res) – blackening Jun 30 '19 at 16:11
  • 5
    Why can't you `await` the `Promise.all` call? i.e. `let result = await Promise.all(data.map(async currentObj => { ... }));` As mentioned by @blackening you have to make your `app.post('/', urlEncodedParser, async (req, req) => { ... }` async too – nbokmans Jun 30 '19 at 16:12
  • 1
    This behavior just makes sense because `Promise.all` by itself returns a `Promise` containing the results as an array, and that `async` functions *will* return `Promise`s. Knowing this, do try `Promise.all(result).then(r => console.log(r))` instead of `console.log(Promise.all(result))` and share with us what output you get! You should be getting something like `[{nodeName: 'somename', nodeStatus: 'somestatus'}]` – ionizer Jun 30 '19 at 20:02

1 Answers1

0

This is because Promise.all() takes a Promise array and returns a Promise, resolving your Promises and put all the resolved Promise results in an array. Also, we need to remember that async functions returns a Promise.

You can try running my below demo snippet:

let myObj = [
  {
    foo: 'some_value',
    bar: false
  },
  {
    foo: 'some_other_value',
    bar: true
  }
]

function baz(isTrue) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 100, isTrue ? 'TRUE!' : 'FALSE!')
  })
}

let noAsync = myObj.map(o => {
  return {
    attr1: o.foo,
    attr2: baz(o.bar)
  }
});

let promises = myObj.map(async o => {
  return {
    attr1: o.foo,
    attr2: await baz(o.bar)
  }
});

console.log('No Async :', noAsync);
console.log('Async    :', Promise.all(promises));

Promise.all(promises).then(r => console.log('Promise.then:', r));

P.S.: You might see "attr2": {} as attr2 having an empty object when you run the snippet, but rest assured when you try it on your local machine it contains Promise { <pending> }

ionizer
  • 1,661
  • 9
  • 22