Here, we have run function that takes a callback, and calls it using setTimout after one seconds. We can then repeat this pattern for calling a callback after two seconds, and then three seconds. Our runner is now complete. We can use this runner to run a callback that simply logs the time to the console.
If you run this code now, you can see that it follows the specification correctly in that the callback is called after one second, two seconds, and then, three seconds. Even though it does satisfy a requirement, you can see that the setTimeout nesting in a run function adds a lot of noise that makes the intent slightly difficult to figure out.
We can make this much easier async/await. The only thing we need is a Promise space delay function, and it is very easy to write. It simply takes a number of milliseconds, and returns a Promise that gets resolved using setTimeout after the given number of milliseconds. That is it.
Now, we can create a runAsync function which is now an async function which is going to still take the callback like before, but inside the function, we now get to use await to pause function execution till the Promise is resolved, and then, we call the callback passing in the time.
Now, we can duplicate this code by simply changing the arguments to the callback. Now, if you copy over the previous call to run, and this time call runAsync, if you go ahead and execute the foo, you can see that it still behaves the same in that the callback is called after one second, two seconds, and then three seconds.
This time, the code is much simpler, thanks to our Promise based tele-function and async/await.