0

An async function I am dealing with, returns multiple values in array

const funcName = async function (arg) {
  ...
  return [val1, val2];
}

While calling this function, I find that it is not possible to directly access individual return values in a syntax:

result1 = await funcName(arg)[0]  
result2 = await funcName(arg)[1]

The only way (known to me so far) it works, is to break it down:

result = await funcName(arg)
result1 = result[0]
result2 = result[1]

Is there a way to "collect" the return directly in a single LOC?
(closely, like r1 = await fn(x)[0])
This works obviously for sync variant, and keeps code much precise, clean, while readable.

Bonus ask: any clue why direct array access is not supported?
By intent, or just missed out?

C. Derx
  • 187
  • 11

3 Answers3

1
const [result1 ,result2]= await funcName(arg)
Wai Ha Lee
  • 7,664
  • 52
  • 54
  • 80
ebyte
  • 969
  • 5
  • 15
1

You can use array destructuring:

const [val1, val2] = await funcName(arg);
D. Pardal
  • 4,876
  • 1
  • 13
  • 32
1

The syntax for the await operator is

await UnaryExpression

Which means that the entire expression will be evaluated before handing over to await. Here is a breakdown of what happens when you have await funcName(arg)[0]

  1. funcName(arg) returns a promise.

  2. [0] is the square brackets notation used on the promise. So, it's getting the property 0 from the promise object.

  3. Since there is no such property, the result of the expression is undefined.

  4. await is called on undefined. Since this isn't a promise, it's treated as if a Promise.resolve(undefined) and so there is nothing to wait to complete.

  5. Code execution continues before the actual promise object from step 1. is complete.

You can force await to consider the returned promise, if you surround the correct part of the expression in brackets or to only use it on the expression that returns a promise:

const simpleAsync = async function () {
  return ["one", "two"];
}

async function main() {
  const foo = await simpleAsync()[0];
  const bar = (await simpleAsync())[0];
//            ^                   ^ 
  const baz = await simpleAsync();

  console.log("foo:", foo);
  console.log("bar:", bar);
  console.log("baz:", baz);
}

main();

However, if you want to directly get both return values, you can simply use destructuring for a multiple assignment:

const simpleAsync = async function () {
  return ["one", "two"];
}

async function main() {
  const [a, b] = await simpleAsync();

  console.log("a:", a);
  console.log("b:", b);
}

main();

This way await is called with an actual promise, rather than a non-promise and after that is resolved, the a and b variables will be assigned.

VLAZ
  • 18,437
  • 8
  • 35
  • 54