Actually, I didn’t know that Callback Hell had its own website!
As mentioned above, generators are used for flow control, which allows for TypeScript (and Babel as well) to allow developers use async/await with functions and transpile the code into generators and promises which are natively supported in ES6 (promises are supported in ES5 as well using a polyfill).
One of the most important things to discuss is the adoption of ECMAScript 6 across browsers and runtimes since async/await heavily relies on ES6 features.
It is safe to say, that if you plan to use it within a Node.js application (assuming you have control over the runtime – or at least using some of the newer Node.js versions), may it be a server-side or an Electron based app, you are good to.
However, when speaking of browsers, this may get a little tricky. Currently, as you can see from this compatibility overview, ES6 is supported in all modern browsers (Edge, Chrome, Firefox and Safari), assuming you are running an up-to-date version.
However if you are making an application for users who are conservative or are using an older browser, you may want to pay attention in the next section.
What about ES5?
Recently, TypeScript 2.0 got released, however as much as everyone was expecting it, the async/await didn’t make it to the 2.0 release. In the end of the beta announcement post, Microsoft explained that they are not going to ship the support of async/await just yet due to implementation issues. The actual progress can be tracked on GitHub – in the feature request #1664 or on the roadmap.
So as of now, if you are targetting older browsers, you will unfortunately have to stick with Promises and callbacks until TypeScript 2.1 makes it to us, however when writing a modern web application (targeting modern browsers), you shouldn’t be afraid of using ES6!
Enough chit-chat, show me!
Alright, alright, let’s take a look at some practical sample:
So in this example, we run RunTest() async function which executes and waits for completion of Test1() and then outputs the result to the console. In Test1() we are calling and waiting for response from Test2() and once we get the response, we proceed forward.
The use of
return new Promiseand
setTimeoutwith a callback also actually demonstrates how you would wrap functions which only support callbacks instead of Promises.
But let’s get back to the original topic, upon “compiling” the code with TypeScript, following code for ES6 is produced:
So as you can see, TypeScript produces an __awaiter function and generators for each of the async functions, also using the yield keyword which altogether mimic the async/await operation.
Using with existing libraries
This example shows how easily you can use TypeScript and an existing library together with async/await flow as opposite to returning and resolving an actual promise. It actually means that you don’t have to wrap the library functions into async functions, but they are going to work out of the box!
Generally, it made our code cleaner and more easy to understand for other developers as well.