In JS, we designed `await` specifically to hide `.then()`, just as we had designed `.then()` because callbacks made tracking control flow (in particular errors) too complex.
I recall that one of our test suites was tens of thousands of lines of code using `then()`. The code was complicated enough that these lines were by and large considered write-only, partly because async loops were really annoying to write, partly because error-handling was non-trivial.
I rewrote that test suite using `Task.spawn` (our prototype for async/await). I don't have the exact numbers in mind, but this decreased the number of LoC by a factor of 2-3 and suddenly people could see the familiar uses of loops and `try`/`catch`.
a().then(() =>
b())
.then(() =>
c())
Compared to await a()
await b()
await c()
Even for this simple case I think it's much clearer. Then look at a more complex case: for( i=0; i<n; i++) {
await a(i) ;
}
Now try re-writing this with then() and see the difference.The latter is more fair, here is a possible solution:
const gen = (function* () {
for (let i = 0; i < n; i++) yield a(i);
})();
const run = next => !next.done && next.value.then(() => run(gen.next()));
run(gen.next());
Or something similar using reduce. But in both cases, it illustrates the point, I guess.But if we are at point we can introduce new keywords/syntax in the language, it would just as well possible to come with something like
a.chain(b, c)
In case you need to pass parameters a.chain([b, p1, p2], c)
And for the latter case const indexes = (function* () {
for (let i = 0; i < n; i++) yield i;
})
a.through(indexes)
The whole idea behind `await` is to make the old intuition work without the ugliness of `.then()`. `f(); await g(); h()` has exactly the expected execution ordering.