Source: 1.,190,000,004,322,36e,+16. Single thread
We often say that "javascript is single-threaded".
The so-called single-threaded, refers to the JS engine is responsible for interpreting and executing JavaScript code of the thread only one. You might call it the main thread.
But there are actually other threads. For example: threads that handle AJAX requests, threads that handle DOM events, timer threads, threads that read and write files (for example, in node. js), and so on. These threads may exist within the JS engine or may exist outside of the JS engine, where we do not differentiate. You might call them worker threads .
Two. Synchronous and asynchronous
Suppose there is a function a:
A(args...);
Synchronization : If the caller is able to get the expected result (i.e. get the expected return value or see the expected effect) when function a returns, then this function is synchronous.
For example:
Math.sqrt(2);console.log(‘Hi‘);
When the first function returns, it gets the expected return value: The square root of 2.
When the second function returns, you see the expected effect: A string is printed in the console.
So both of these functions are synchronous.
Async : If the caller is not able to get the expected result when function a returns, it needs to be obtained in the future by some means, then the function is asynchronous.
For example:
fs.readFile(‘foo.txt‘, ‘utf8‘, function(err, data) { console.log(data);});
In the above code, we want to fs.readFile
read the contents of the file Foo.txt through the function and print it out.
But fs.readFile
when the function returns, we expect the result to not happen, but to wait until all the files have been read. If the file is large, it may take a long time.
Here's an example of an AJAX request that looks at the difference between synchronous and asynchronous:
main thread:"Hello, ajax thread." Please send an HTTP request for me, I have the request address and parameters to you. ”
Ajax Thread:"OK, the main thread." I'll send it right away, but it may take some time, you can go ahead and do something else. ”
main thread:: "Thank you, you get a response and tell me." ”
(then the main thread does something else.) After a meal of time, it received a notification of the arrival of the response. )
main thread:"Hello, ajax thread." Please send an HTTP request for me, I have the request address and parameters to you. ”
Ajax Thread:"..."
main thread:: "Hey, Ajax thread, why don't you talk?" ”
Ajax Thread:"..."
main thread:: "Hey! Hey, hey, hey! ”
Ajax Thread:"..."
(After a moxa of fragrant time)
main thread:: "Hey! Please say something! ”
Ajax Thread:"Main thread, I'm sorry, I can't talk at work." Your request has been sent out, get the response data, to you. ”
It is because JavaScript is single-threaded, and asynchronous is easy to implement non-blocking, so in JavaScript for time-consuming operations or the operation of uncertain times, the use of asynchronous is a necessary choice. Async is the focus of this article.
Three. Elements of an asynchronous process
As you can see from the above, the 异步函数
call is actually done quickly. But there are a number of steps behind the worker thread performing the asynchronous task, the notification main thread, the main thread calling the callback function, and so on. We call the whole process 异步过程
. The invocation of an asynchronous function is only a small part of the entire asynchronous process.
To summarize, an asynchronous process is usually the case:
The main thread initiates an asynchronous request, and the corresponding worker thread receives the request and informs the main thread that it has received it (the asynchronous function returns); The main thread can continue executing the following code while the worker thread executes the asynchronous task, the main thread is notified after the worker has finished the work, and the main thread receives the notification and executes a certain action (call the callback
Asynchronous functions typically have the following form:
A(args..., callbackFn)
It can be called an initiating function of an asynchronous process, or an asynchronous task registration function. args
is the parameter required by this function. callbackFn
It is also the parameter of this function, but it is more special, so it is listed separately.
So, from the main thread point of view, an asynchronous process consists of the following two elements:
They are all called on the main thread, where the registration function is used to initiate the asynchronous process, and the callback function is used to process the result.
To give a specific example:
setTimeout(fn, 1000);
One of these is the setTimeout
initiating function of the asynchronous process, which fn
is the callback function.
Note: The previously stated form A(args..., callbackFn)
is an abstract representation and does not necessarily mean that the callback function must be the argument for the initiating function, for example:
var xhr = new XMLHttpRequest();xhr.onreadystatechange = xxx; // 添加回调函数xhr.open(‘GET‘, url);xhr.send(); // 发起函数
The initiating function and the callback function are separate.
Four. Message Queuing and Event loops
As mentioned above, during an asynchronous process, the worker thread needs to notify the main thread after the asynchronous operation is complete. So how does this notification mechanism be implemented? The answer is to take advantage of Message Queuing and event loops.
To summarize in a sentence:
The worker thread puts the message in the message queue, and the main thread takes the message through the event loop process.
Message Queuing : Message Queuing is a first-in-one-out queue that contains various messages.
Event Loop : The event loop is the process by which the main thread repeatedly takes messages from the message queue and executes them.
In fact, the main thread will only do one thing, that is, to take messages from the message queue, execute the message, then fetch the message, and then execute. When Message Queuing is empty, it waits until the message queue becomes non-empty. And the main thread is only going to fetch the next message after the current message has been executed. This mechanism is called the event loop mechanism, and the process of taking a message and executing it is called a loop.
The event loop is expressed in code that is probably the case:
while(true) { var message = queue.get(); execute(message);}
So, what exactly is the message in Message Queuing? The exact structure of the message is of course related to the specific implementation, but for the sake of simplicity, we can assume that:
The message is the callback function that was added when the asynchronous task was registered.
Again, for example asynchronous Ajax, suppose the following code exists:
$.ajax(‘http://segmentfault.com‘, function(resp) { console.log(‘我是响应:‘, resp);});// 其他代码.........
The main thread continues to execute additional code after the AJAX request is initiated. The AJAX thread is responsible for requesting segmentfault.com, and when it gets a response, it encapsulates the response into a JavaScript object and constructs a message:
// 消息队列中的消息就长这个样子var message = function () { callbackFn(response);}
This callbackFn
is the callback function in the previous code when the response was successful.
When the main thread finishes executing all the code in the current loop, it takes the message (that is, the function) out of the message queue message
and executes it. At this end, the callback function is executed when the worker thread is finished with the main path 通知
. If a callback function is not provided at the beginning of the main thread, the AJAX thread does not have to notify the main thread after receiving the HTTP response, and there is no need to put the message in the message queue.
The diagram shows that this process is:
From the above we can also get the obvious conclusion that:
The callback function of the asynchronous procedure must not be executed in the current round of event loops.
Five. Asynchronous and event
The "event loop" mentioned above, why is there a? 事件
That's because:
Each message in the message queue actually corresponds to an event.
There has been no mention of a very important asynchronous process:DOM events .
For example:
var button = document.getElement(‘#btn‘);button.addEventListener(‘click‘, function(e) { console.log();});
From an event point of view, the code above indicates that a mouse click event Listener is added to the button, and the event listener function is invoked when the user taps the button and the mouse click event Triggers.
From the point of view of the asynchronous process, the addEventListener
function is the initiating function of the asynchronous process, and the event listener function is the callback function of the asynchronous process. When an event is triggered, the asynchronous task completes and the event listener function is encapsulated into a message queue, waiting for the main thread to execute.
The concept of an event is not really necessary, and the event mechanism is actually the notification mechanism of the asynchronous process. I think it exists for the programming interface to be more friendly to developers.
On the other hand, all asynchronous processes can also be described by events. For example, setTimeout
you can consider a corresponding 时间到了!
event. The previous article setTimeout(fn, 1000);
can be seen as:
timer.addEventListener(‘timeout‘, 1000, fn);
Six. Producers and consumers
From the producer and consumer point of view, the asynchronous process is this:
The worker thread is the producer and the main thread is the consumer (only one consumer). The worker thread executes the asynchronous task, encapsulates the corresponding callback function into the message queue after the execution completes, and the main thread continuously takes the message from the message queue and executes it when the message queue is empty and the main thread blocks until the message queue is again non-empty.
Seven. Summarize
Finally, I'll summarize it in a life example. Synchronous and asynchronous: On the road, the car is one by one, the orderly operation. At this time, a car broke down. If it stops in place to repair, then the car behind will be blocked unable to travel, the traffic is chaos. Fortunately, there is an emergency lane, which can be used to push the faulty vehicle to the emergency lane for repair, while normal traffic will not be affected. The bus is repaired, and then back to the normal lane from the emergency lane. The only effect is that there are more emergency lanes, and the order between the original vehicles is a bit messy.
This is the difference between synchronous and asynchronous. Synchronization ensures that the order is consistent, but is prone to blocking, and async solves the blocking problem, but changes the order. It's not a big deal to change the order, just to make the program slightly harder to understand:)
JavaScript: Thorough understanding of synchronous, asynchronous, and event loops (turn)