|Written by Ian Elliot|
|Monday, 01 January 2018|
Page 2 of 2
Where Does The Thread Go?
The question is, what does the thread do while a function is paused because of an await?
There are many ways of answering this and ways of thinking about it, but the best is to imagine that the await behaves like a return that can be resumed. When a function executes an await, the thread returns to the calling program which receives the Promise object created by the async function in a pending state. It really is as if a return had been executed, the only difference is that the function can resume when the Promise it is waiting for is settled.
If you find this behavior odd it is worth pointing out that it is also the way that the yield command works. A yield lets the thread resume from the point that the function was called just like a return, but again with the option of restarting.
For example consider the example:
What happens when myFunction is called is that the first await causes a Promise to be returned which resolves after three seconds to the value of first+second.
You can think of this as being equivalent to:
This behavior has some consequences that are worth pointing out.
The first is that you can only write code that looks synchronous within an async function. At the top level you still have to work with Promises.
The second is that it is difficult, but not impossible, to use await to allow the UI thread to service the event queue. The problem is that when you use the await command the UI thread continues to run the code that called the function, and the UI thread is only freed when this terminates.
There is also the small matter that the async function cannot resume while the thread is busy running other code. In other words, the thread has to be freed and goes back to servicing the event queue in order for the async function to be resumed, or put another way the async function is resumed asynchronously.
This has a strange consequence. The first await in an async function lets the calling program continue, but the function will only resume if the calling function has terminated. This means that that any second or subsequent await in an async function will only be executed after the calling program has terminated.
Some simple examples will help make these ideas clearer.
Consider a simple pause function:
You can see the general idea is to await a Promise that takes t milliseconds to resolve. There are two console.log commands that serve to give the time before and after the await.
If you try it out from the main program:
you will see the before and after messages separated by about a second. However, if you try it out using;
You will see:
followed a second later by:
This should make sense if you have followed the idea that the await returns the Promise in a pending state. What happens is that “Before call” and “before” are displayed without delay, but then instead of waiting for one second the await returns control to the main program which immediately prints “After call” and then frees the UI thread. One second later the Promise resolves and the function resumes to print “after”. Not the order of events you were hoping for.
If you change the program to:
then you will see the one second delay and the messages “Before call/before” followed one second later by “after/After call”.
Also notice that the await cannot be resumed until the main program has completed and this means if it is long running then the delay could be much longer than one second.
Async & Await Summary
If you understand the simplicity of the way that async and await work then how to use them should be obvious, but it is worth making sure that everything is clear and it is worth looking at some potential problems.
Now Available as a Print Book:
You can buy it from: Amazon
or email your comment to: email@example.com
|Last Updated ( Wednesday, 03 January 2018 )|