The solution is async functions. Inside of an async function, you can await for a promise to complete. Let’s look at how we can modify the current sequentially executed promise chain using async and await. So the doStuffSequentially function, to get started I’m just goanna go ahead and delete these last lines of code, the last .thens that we added to the doStuffSequentially function. And what I’m goanna go ahead and do is I need to make this into an async function. So you make an async function, simply by typing async right in front of the function declaration.
And I’m goanna get rid of this Promise.resolve call, and we will operate this function right between the brackets. So what an async function allows us to do is write code that appears synchronous. So we can write code line-by-line, and we can tell certain lines to wait for a result before executing any further. So I’ll just go ahead and add a console.log starting. Seems to be the first thing that we have. And now, inside of an async function, I can use the await key word, with a promise. So this await will await a delay of one second.
So before we execute any code found on line 13 and beyond, we will wait for the delay promise to be resolved. So I’ll go ahead and console.log waiting. And then we can await another delay. And I’ll go ahead and await a writeFile. So this works with any promise. And we’ve created a writeFile promise using the utilities promisify function.
So we will write some sample text to this file. And when we’re done writing the file, we’ll go ahead and beep. We can just invoke that as a function. So file.txt created. And then after we create that file, we’ll go ahead and await another delay. We’ll wait for three seconds. And then we will await the unlink promise, file.txt. So we’re doing the exact same thing that we did with the thenables, but notice this code looks a little bit more synchronous.
It’s a little cleaner to edit. There we go. So now I can get rid of this entire .then chain, because the doStuffSequentially function will still operate sequentially. It still uses promises, but as opposed to wiring up every handler and additional then statements, we can actually write the code line-by-line and just call certain lines to wait. Let’s go ahead and run this and see what happens in our terminal.
And here we see roughly the same results. Now since we didn’t see this in the last lesson, I’m goanna go ahead and open up my files. So here’s my project folder. I got there by typing command backslash. Let’s go ahead and run it again, just so we can see that file getting created. And being removed. So there’s file.txt. One of the benefits of writing code this way is we can handle errors with tryCatch blocks. That will allow us to specify what errors we want to handle exactly. Like, for instance, I could put a try, and catch block around this writeFile and beep.
And I can handle the error that way. So now if anything goes wrong with writing the file, we can go ahead and add that error, or we can actually create a new error, if we wanted to. We could surround the entire function in a tryCatch block if we wanted to. That would be available to us, as well. And then finally, if we wanted to keep the doStuffSequentially function working the exact way it did in the past, it would need to return a promise. So all we need to do is return Promise.resolve. And now in this case, the return is not direct style.
So because we’re in a asynchronous function, all of these lines that have awaits are gonna wait before processing any further, so we will wait for the file to be unlinked before we return a resolved promise. And just returning that promise resolve, allows me to then dot chain extra thenables on here, or use the doStuffSequentially within its own async await function. Now, I do want to delete this and actually show one more quick example. So there is one more thing that I want to show you about asynchronous functions before we move on, and that is that we can also obtain data from them.
So let’s say that we wanted to use a read directory promise. We can go ahead and create one up here, readdir. And the readdir will read our directory, because we’re goanna promisify the fs.readdir method. So if I were to execute this promise, readdir, and say .then, I would actually get the files as an argument passed to the thenable, because the read directory promise is goanna read directory and then give me a result.
So we can also obtain the data that would be resolved in a promise in an async await function, too. I’ll give you an example. We’ll go ahead an create an async function, async function start. And when we go ahead and start this program, we will get the files by saying var files equal the result of await. So we’re still using the promise. Go ahead and read the files in the current directory. And then I can go ahead and log those results.
So because the readdir is a promise, we are still waiting for it to be resolved before moving to line 14. Any data that the readdir promise would return, we can actually set using an equal sign, because line 13 is going to await for readdir to resolve and return its results. So let’s go ahead and give this a shot. I can clear out my current terminal, type node dot one more time. Oops, I better call start. So we put it in an asynchronous function called start, and then forgot to invoke it. So let me go ahead and add that and try this one more time, over in the terminal, node dot.
And we can see that we have two files in the current directory. So asynchronous functions give us a really nice way to organize our code in a more manageable fashion.