12

As far as I can tell, both the spec and the documentation have await as the only reserved keyword out of the async/await feature.

This is further demonstrated by the fact that we can name a variable async:

For example:

var async = 5;
console.log(async) // this is fine

Node (6.10) (also on Repl.it)

Node

Chrome (59)

Chrome

Firefox (54)

Firefox

Is it because of backwards compatibility? I'd guess many codebases would use the name async for certain features.

This allows for some strange looking code examples:

async function async() {
  var async = 5;
  await async;
  return async;
}
async().then(console.log)

Infinite recursive promise chain? (Not really important since any function name would allow this, however this code looks additionally confusing)

async function async() {
  await async();
}
// stackoverflow (might need to open your console to see the output)
nem035
  • 34,790
  • 6
  • 87
  • 99
  • Part of this probably has to do with the more limited use of `await`; `await` can only be used inside of an `async` function, so outside of these functions await could still be used for other things (though I imagine this is not recommended for clarity's sake). – SimplyComplexable Jul 26 '17 at 20:42
  • I think one of the big goals of the committee is to not break the web with updates to the specification. Part of that compromise is making some awkward-looking decisions that may appear inconsistent, but are just necessarily to keep everyone from pulling their hair out from having things broken. For instance, take [caolan/async](https://caolan.github.io/async/), one of the most popular pre-promise era asynchronous utilities in use. If `async` was a reserved keyword, that would disrupt a _lot_ of codebases, and cause some re-branding issues as well. – Patrick Roberts Jul 26 '17 at 20:43
  • Just take the popular (during the 0.10.x era) node module with the same name. Can't risk breaking a noticeable part of the ecosystem. – marvinhagemeister Jul 26 '17 at 20:45
  • Yeah, it makes sense that backwards-compatibility is the most likely reason, just wondering if there's an exact, official answer anywhere. – nem035 Jul 26 '17 at 20:51

1 Answers1

14

async does not need to be a reserved word, because it can be uniquely identified. The contexts in which it can occur are those such as

async function() { }
async () => { }
obj = { async foo() { } };

All of these could not be parsed in any way other than seeing async as indicating an async function.

On the other hand, await can in theory be used in a statement such as

async function foo() {
  await(1);
}

which is ambiguous; is await awaiting the value 1, or is it a function being called with the parameter 1? Therefore, await needs to be a reserved word (inside async functions; outside, feel free to use it as a variable).

Remember that JavaScript has evolved greatly since its origin. Many words were designated as reserved, and then never used, or designated as reserved when technically they might not need to have been. The designation of await as a reserved word (within modules), and the non-designation of async as a reserved word, are the product of a more mature understanding of the language on the part of its designers.

  • I don't know if `const` can be uniquely identified. `let const = 1; const = 2` for example comes to mind. – Rodrigo Leite Jul 26 '17 at 21:06
  • 2
    I think @nem035's confusion about async not being clear in all of it's contexts comes from assuming `async () => {}` could apply to the keyword or a function called `async` but here the ambiguity is solved by the presence of `=>` as arrow functions cannot be named functions (accept by assigning them with an `=` operator). – Jason Sperske Jul 26 '17 at 21:08
  • 1
    An if statement would be ambiguous too because it could be read as a function call with parameters followed by a separate statement. – fgb Jul 26 '17 at 21:13
  • @JasonSperske my issue isn't with understanding if `async` keyword is clear in all contexts or non-ambiguous. My issue is that, even though `async` is non-ambiguous in its usage, allowing variables to be named with the word `async` can still provide some confusing code (as I tried to show), particularly with proper syntax highlighting and thus feels awkward. I also don't understand how "all of these would be invalid if `async` were a variable" when putting `var async = 5` above them would clearly not break the code. – nem035 Jul 26 '17 at 21:15
  • It's invalid if async is parsed as a variable name. Like you can't write `variable function() {}` – fgb Jul 26 '17 at 21:21
  • @fgb but when you say `var async = 5; async function (){}` you are doing just that, and it's valid. I understand that the engine can distinguish between the context of a variable name and a function declaration, just doesn't seem like it's a good enough reason to allow this. – nem035 Jul 26 '17 at 21:23
  • @torazaburo thanks for the clarification, would you care to explain (or point to a resource that does) of why this looser semantic is a more mature design? At a basic level, having `async` as a non-reserved word just seems like would cause confusion and no real benefits. – nem035 Jul 26 '17 at 21:51