async / await should really be thought as a better way to use Promises reliably and safely with less chances of programming errors.
This lesson covers the fundamentals of annotating a function as async. An async
function gets the chance to use the await
keyword. This lesson covers the usages of these keywords.
Instructor: [00:00] The make a function async, all you need to do is prefix it with the async keyword. Async can be used with simple functions, error functions, and class methods. Let's discuss the nature of async functions in isolation by focusing in on a simple function.
[00:20] An async function always returns a promise. The promise resolves to the value that is returned by the function. Here, the function returns an implicit return of all JavaScript functions, which is undefined. If we log out the value, you can see that is going to be undefined.
[00:46] If we return a value from that function, of course, the promise will resolve to that value. TypeScript is smart enough to infer the return type for async functions to be the promise of the returned values. With the return value of async functions out of the way, let's focus in on the body of an async function.
[01:13] We set up Node.js to ignore any unhandled promise rejections to have a clean console. Next, we set up a few promises to use in our async function. We create a variable that is not a promise. We create a promise that will resolve. Finally, we also create a promise that will reject.
[01:33] Async functions get access to the await operator in their function bodies. The await operator can be applied to any variable. If the variable is not a promise, the value returned for the await operator is same as the variable.
[01:55] If the variable is a promise, execution in the function body pauses until the fate of the promise is determined. If the promise resolves the value of the await operator, it's the resolve value of the promise. If the variable is a promise that gets rejected, the await operator throws an error in the body of the async function.
[02:16] This means no subsequent statements execute unless there is a catch construct, similar to try/catch in synchronous code. Let's go ahead and call this function to verify that it works as explained. The not a promise variable just resolves to itself. The promise that will resolve returns its final resolved value, and the promise that gets rejected interacts with the try/catch as expected.
[02:51] If a promise takes some time to settle in its fate, execution at the await operator pauses until the fate is determined. Here, we are going to wait five seconds before determining the fate of this local promise. If we go ahead and run this code, you can see that the execution pauses for five seconds, and then the next line, done waiting, is executed.
[03:18] Essentially, async await allows you write asynchronous code based on promises in a manner that allows you to reuse your synchronous code writing skills.
What’s the best practice when I have async operations inside of my constructor
Add an async
init
method e.g. new Foo().init().then
and so on 🌹
This is inside of an Angular component, I don't explicitly call new Component()
, the framework does it for me. Would I put this logic inside ngOnInit?
This is inside of an Angular component, I don't explicitly call
new Component()
, the framework does it for me. Would I put this logic inside ngOnInit?
That would work. However angular will not wait for for the promise chain to complete.
Good to know
I tried making a constructor function async, and typescript yelled at me. What’s the best practice when I have async operations inside of my constructor? Continue using
.then(() => { … })
? Refactor the async code somewhere else?