|
|
|
|
|
by robertknight
1569 days ago
|
|
Async functions are conceptually quite similar to ES6 generator functions. In an ES6 generator every `yield` expression is a point where the function can be paused and later resumed. With an async function it is an `await`. The difference between a generator and an async function is that whereas the caller manually resumes generators by calling (`next`) on the generator, async functions are automatically resumed when they yield a promise that is resolved. Making a function support being paused and resumed requires changes in how the function is run and the data that is maintained while it is executing. In addition to behaving differently than sync functions when they execute, the results are also handled differently. Async functions always return a promise - whether they `return` a literal value, return another promise or throw an exception. Due to these differences, it makes sense that the special nature of async functions and generators must be declared up-front, with the `async` keyword or `*` for generators. It would be possible to design the language such that the function type was determined by looking at whether it contains `yield` or `await` keywords. Python does this with generator functions. However this makes an important aspect of behavior less explicit. |
|
1. Rewrite the async function to be a generator function with a wrapper that calls `next` on the generator whenever `await`-ed Promises resolve
2. Rewrite the generator function to be a big switch statement, together with a wrapper function that drives execution.
You can play around with generators and async functions in the TypeScript playground, with TSConfig set to target ES5, to see how this works: https://www.typescriptlang.org/play?target=1#code/GYVwdgxgLg...