Karel Bílek Karel Bílek - 3 months ago 12
Javascript Question

What should happen with `await` when the expression after the keyword does not evaluate to promise?

I have a ES7 code like this.

async function returnsfive() {
var three = 3;
var threeP = await three;
return threeP+2;
}

returnsfive().then(k=>console.log(k), e=>console.error("err", e))


What should happen at the
var threeP = await three
line?

Should the code continue as expected, or fail, because
three
is not a promise?

In this repo, it is mentioned as "Debatable Syntax & Semantics". I am not able to read through the official documentation to find the exact definition, since it's too technical.

Default babel.js transformation logs 5 as expected; however,
nodent
- a different transform - prints
TypeError: three.then is not a function
. Which is correct and why?

Answer

According to the current working draft spec, the runtime should "cast" the awaited value to a promise first:

AsyncFunctionAwait ( value )

  1. Let asyncContext be the running execution context.
  2. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  3. Let resolveResult be ! Call(promiseCapability.[[Resolve]], undefined, value).
  4. ...

Step 2 and 3 combined is roughly equivalent to calling Promise.resolve(value), which creates a new promise that is resolved with the given value or - if the value is a thenable - will follow that thenable.

In other words: await 3 is equivalent to await Promise.resolve(3), and Babel implements the spec correctly.

nodent on the other hand deliberately does not support awaiting a non-promise by default. There's a wrapAwait option available if you want all awaited values to be wrapped in a promise first, but the nodent documentation reports that this may affect performance.