Write at the front – the manual for this article
I’ve been thinking a lot about why asynchrony is so hard to master. There are two answers:
- I may not have grasped all the internal structure, but I think I understand it. In fact, I have been operating in the black box, so there is a bug and I don’t know how to do it.
- Time. Asynchrony is complicated because it has a time dimension. I struggled to learn asynchrony myself because most of the material was written about this high-latitude process. So I decided to make asynchrony all GIfs, using animation to explain time, hoping to help you understand asynchrony more efficiently.
- Part1 setTimeout and eventloop
- Part2 Promise and MiscroTask Queue
- part3 generator… Yield and async… Await, I am dying while making animation. If you think it is ok, please give me a thumbs up.
Part1 setTimeout works
I. What is asynchronous?
- Definition of asynchrony
In theory, one person must be able to harvest wheat more slowly than multiple people, such as network request, delegate to another thread, do not occupy the main thread, multiple threads is more powerful.
The main purpose is to be fast
. There’s also asynchrony
uncontrolled
Asynchrony needs to manage time. Although asynchrony is slow, sequential execution is very reliable, while asynchrony needs to think about how to manage extra threads and when to receive results. What if the thread strikes the next program? That’s the price of being fast.
Ii.settimeout What exactly happened
1) setTimeout construction principle – it is not native JS
Javascript is a single-threaded language. It has only one thread or callback stack. There is no asynchrony in native JS.
In fact:
- Asynchrony is a function of JS invoking the Web API provided by the browser.
- A structural model of a V8 engine. The following is my simplified version, you need to know what the function of each area is:
- Javascript source runtime area,
Responsible for storing data and computing data
.- The Call Stack and Javascript Source belong to the same V8 engine, and the callback stores the context that the function needs to execute,
It mainly manages the running sequence
.- The WEB API is provided by Browser and contains many asynchronous functions such as setTimeout timers, Network requests (XHR) and events.
3) Operation principle of setTimeout — Eventloop and Task Queue
This code is very basic, the purpose of the explanation is to clarify how JS works.
- JS will initially create a global function, which is not normally present by default. encounter
setTimeout
The functioncb
Passed to browser(or Web API), this code blocks (Turn red
) Jump executionsayHello
sayHello
After execution (Turn green
),sayHello
Out of the stack
- After 1000ms, Browser puts the function
cb
Throw it into the CallStack, executecb()
, all execute the defaultglobal
Also out of the stack
3) Introduction of event loop
If setTimeout is 0, who comes first and who comes last? If the answer is not clear, there is still one piece of the puzzle missing to complete the operation of setTimeout.
Let’s take a look at the execution of the code
1. We will start with global being pushed directly. SetTimeout enters browser and continues execution after masking.
2.
sayHello
Functions are registered in memory(heap) and then executed. But at the moment,
setTimeout
And it comes back,
Who should be on the stack first?Introduced 3.
eventloop, before browser’s function enters the Call Stack
task queueAlso known as the Macro Queue (
Water is blue
). Evenloop is a logic,
When the CallStack is empty it pushes the queue function onto the stack
. In this case, the stack contains global, cannot be pushed, run first
sayHello("First!" )
.Global () is still there, continue to execute console.log(“second!” ).
4.
Finally, the Call Stack is empty. The callback() function is pushed into the stack.
Part2 Promises waiting for results
I. Operation principle of Promise — “it” will run automatically when conditions are met
This is one of the pieces of the puzzle for understanding async await, so it’s important to understand how promise objects work.
- As soon as the promise executes, an Object is returned to place the fetchPromise. And sends browser a request to call the XHR network. That’s the end of the code.
- Promise. Then assigns value to the ondepressing attribute of this placeholder object, which will be triggered only when the value has a value. At present, it will not be triggered.
- After adding 200s, it returns value: “hi”, which passes back the Promise object and updates value to “hi”, at which point the display function in onFullfill fires.
II. Promise vs. setTimeout — Miscro Task Queue
In the following code, we can see that when executing the setTimeout and promise returns, the first and last problem will occur. In this case, we can introduce the concept of Micro Task Queue to control the order.
- After setTimout is executed, it enters the Task Queue, fetchPromise sends an asynchronous request to the network, and the JS part has been executed. Next, blockFor500ms to block the main thread.
- If the promise returns after 200ms, the function display is triggered, but the call stack still has functions running. There’s no way to execute so at least let the function have somewhere to wait. We might expect display to be pushed into the Task queue, but in fact display will be pushed into a new queue
micro task queue
Wait.
task queue
andmicro task queue
All followCall stack is pushed when the call stack is empty
The rules. butmicro task queue
Display is executed first, and setTimeout is executed last.
"Me first!" "Hi" //promise "Hello" //setTimeout Copy the code
Part3 Async await pull and push
I. How the generator works — the suspension of yield
So here’s the code, and you can guess without looking at the answer, what is the answer?
Element2 = 7!!
The steps are as follows:
- Generator createFlow() returns an object with a pointer to Next pointing to createFlow(LinkedList?).
- ReturnNextElement. Next () points to createFlow, executes createFlow, and returns yield to newNum assignment.
Yield is a very strong instruction, higher than =, and num returns to element1 before newNum completes the assignment
Yield also performs another functionThe pause button is pressed for the current execution context
- Element2 is executed, and then next(2) passes a value, and then createFlow is called
The function does not restart the new execution context but continues execution on the original basis
, newNum did not complete the assignment, and the value passed in will automatically fill in the assigned variable.newNum=2
, yield newNum+5, and follow the same pattern.
II. Async await is just syntactic sugar for generator+ Promise
Let’s start with a bit of async await code
It’s actually the same thing as the code below
Let’s take a look at the order in which asynchrony is added:
1. FutureData yields a promise at yield, and createFlow is paused. The data inside createFlow has not yet been assigned a value.
2. The Promise calls the Web API execution, for example, returns a result “Hi” after 200s. According to the promise mechanism, the result will trigger the execution of doWhenBack, and the doWhenBack will enter the Micro Task Queue for execution.
The event loop waits until the stack is empty and pushes doWhenBack to the stack. The createFlow function is called when the stack is empty. Data is automatically padded with the promise’s return value ‘Hi’, printing out the result.
// Execute result "Me First! "Me second!" "Hi"Copy the code