7

Why I can't access object properties with a . in async await return object? I know that I can access the properties like below.

let val1 = await call(3);
let val2 = await call(4);

but I'm interested if this can be done

let v = await call(3).val + await call(4).val;

const call = (x) => {

    return new Promise((resolve, reject) => {

        setTimeout(() => {
            resolve({
                val: x
            });
        }, 3000)
    })
}

const dummy = async () => {

    //let val1 = await call(3);
    //let val2 = await call(4);
    //alert(value.val + val2.val);
    let v = await call(3).val + await call(4).val;
    alert(v);
}

dummy()
Calvin Nunes
  • 6,376
  • 4
  • 20
  • 48
noone
  • 6,168
  • 2
  • 42
  • 51
  • 1
    Not exactly shorter: `let v = await Promise.all([call(3), call(4)]).then(res => res.reduce((a, c) => a + c.val, 0));` this way you don't have multiple handwritten lines, and it takes 3 seconds total. –  Jul 19 '19 at 12:14
  • 2
    I think it should work like this: `let v = (await call(3)).val + (await call(4)).val;` – phip1611 Jul 19 '19 at 12:14

4 Answers4

6

You're trying to await the value of the val property of the promise.

You need to await the promise and then read the val property from the result: (await call(3)).val

const call = (x) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({
                val: x
            });
        }, 3000)
    })
}

const dummy = async () => {
    let v = (await call(3)).val + (await call(4)).val;
    alert(v);
}

dummy()
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
5

Just wrap the await and the expression to await in parens. Then access the property.

const call = (x) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        val: x
      });
    }, 3000)
  })
}

const dummy = async() => {
  let v = (await call(3)).val + (await call(4)).val;
  alert(v);
}

dummy()

Do note that doing it this way, you're awaiting 3 seconds for the first call, then awaiting another 3 seconds for the second call. Unless the second call is somehow reliant on the first, I suggest you do the following:

const call = (x) => {

  return new Promise((resolve, reject) => {

    setTimeout(() => {
      resolve({
        val: x
      });
    }, 3000)
  })
}

const dummy = async() => {
  // Call both in parallel
  let val1 = call(3);
  let val2 = call(4);
  
  // Await for both
  let v = await Promise.all([val1, val2]);
  
  // *then* add
  alert(v[0].val + v[1].val);
}

dummy()
Joseph
  • 117,725
  • 30
  • 181
  • 234
2

Why I can't access object properties with a . in async await return object?

Because call returns a Promise and thus has no property val. When you await the returned Promise, the expression await call(x) will eventually resolve to {val: x}, which you can then use .val on.

Thus, you can either await each call separately and save the returned object in their own variables, or wrap your expression await call(x) in parenthesis of their own, such that you are getting the .val of the resolved value, not the promise:

const call = (x) => {

  return new Promise((resolve, reject) => {

    setTimeout(() => {
      resolve({
        val: x
      });
    }, 3000)
  })
}

const dummy = async() => {
  let v = (await call(3)).val + (await call(4)).val;
  alert(v);
}

dummy()
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
0

This is because the call does not return a direct result object. It is returning a promise which will resolve value in .then callback. You can await this call.

const call = (x) => {

    return new Promise((resolve, reject) => {

        setTimeout(() => {
            resolve({
                val: x
            });
        }, 3000)
    })
}

const dummy = async () => {

    //let val1 = await call(3);
    //let val2 = await call(4);
    //alert(value.val + val2.val);
    let v = await call(3).then(result => result.val) + await call(4).then((result)=> result.val);
    alert(v);
}

dummy()
Manish Khedekar
  • 392
  • 3
  • 13