Single threaded model
The single-threaded model of JS means that JS runs on only one thread. Note, however, that this does not mean that JS has a single thread, in fact JS has multiple threads, but why run on a single thread is a historical issue.
Because JS was designed not to make browsers too complex, and because multiple threads share resources and influence each other’s performance, this is a bit more complicated for Web pages. Let’s say one thread inserts a DOM node and another thread removes the DOM node at the same time. So to keep scripting languages from becoming too complex, JS is designed to be single-threaded.
This design has both advantages and disadvantages: the advantages are clear logic and simple execution environment. The disadvantage is that when a task takes a long time to execute, there will be a waiting period for subsequent tasks, which delays the whole program.
In many cases, JS code will not load CPU resources in large quantities, but is similar to AJAX and other tasks that request server resources. Such tasks are often in the state of waiting for the return result. If there is no return for a long time, then the whole program will be at a standstill.
At this point, the JS designers realized that they could suspend some of the waiting tasks and perform other operations until the waiting tasks returned results, and then go back to execute them. This mechanism is the JS Event loop mechanism.
Thus, JS becomes synchronous and asynchronous. Synchronous tasks are performed on the main thread and asynchronous tasks are coordinated on other child threads, but JS is essentially a single thread because child threads cannot manipulate the DOM and are completely controlled by the main thread.
Synchronous task && Asynchronous task
A synchronous task is a task that is not suspended by the JS engine and is executed sequentially on the main thread.
An asynchronous task is a task that is suspended by the JS engine and put into the task queue. Only when the JS engine thinks it is ready, it will return to the asynchronous task. Take an AJAX example:
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function (){};
req.onerror = function (){};
req.send();
console.log(1)
Copy the code
In the above code, req.send will send a request to the server, which is not completed until the server receives the complete result. In this case, it is an asynchronous task, so after this function is called, it will execute the following code directly, and then call the function when Ajax returns the result. If this is a synchronous task (which can be set to synchronous on the open function), the rest of the code will wait for the Ajax results to return.
We can understand: synchronization is directly can obtain the result, asynchronous can not directly obtain the result.
Task queue
A task queue is a container for asynchronous tasks that need to be executed. There are actually multiple queues depending on the type of asynchronous task. Let’s say there’s only one.
The sequence of JS execution is as follows: First, all synchronous tasks on the main thread will be executed. After the synchronization task is executed, when certain conditions are met, JS will take out asynchronous tasks from the task queue and continue to run them on the main thread. Then the asynchronous task becomes a synchronous task, and the next asynchronous task will be put on the main thread until all the asynchronous tasks on the task queue are cleared and the program is finished.
The main thread reads events from the “task queue” in a continuous Loop, so the whole operation mechanism is also called an Event Loop.
The callback function
Asynchronous operations typically use the callback function, which is executed once the task enters the main thread.
function f1(){}
function f2(){}
f1()
f2()
Copy the code
If the above code is synchronized, f1 must be executed before f2 is executed. So, can we execute F2 first and then f1?
The answer is we can use the callback function, so we change the code to the following
function f1(){}
function f2(callback){
callback()
}
f2(f1)
Copy the code
The above code is a callback function. The code executes F2 and then f1, which is a callback function. But the code above is actually a synchronous callback rather than an asynchronous one.
Determining asynchronous tasks
Here are some examples of common asynchronous tasks. They are asynchronous tasks if the callback function is inside one of three things.
1. AJAX (AJAX can set synchronization, but don’t do it unless your project manager wants to do it 😂😂)
2, setTimeout
3, the addEventListener
AJAX example
Let’s look at a piece of code
const request = new XMLHttpRequest() // readystate=0 request.open('get', '5.json', False) / / false here set the AJAX into synchronous readystate = 1 let n = 1 request. Onreadystatechange = () = > {the console. The log (" state: " + request.readyState) n += 1 if (request.readyState === 4 & (request.status >= 200 && request.status < 300)) { Console. log(' final n is :'+n); }} request. Send () // readyState =2 console.log(' I am the code behind '); console.log(`n:` + n);Copy the code
When request.send() is executed, the request will be sent to the server. The following two lines of console code will not be executed. OnreadyStatechange is called when listening for readyState. The readyState of the Request instance object is 2 after send is sent. The readyState of the request instance object is 3 when the server responds and downloads some content. The readyState of the request instance object is 4 when the download is completed. Request waits until readyState is 4, then executes the onReadyStatechange callback, and finally executes the bottom two lines of console code, so the result is:
State: 4 the final n is: 2 and I am the following code n: 2Copy the code
However, if request.open(‘get’, ‘5.json’) is set to AJAX, the default AJAX task is asynchronous, then when Request.send () sends the request, the subsequent task will be suspended by the JS engine, and the remaining two lines of console code will be executed first. Onreadystatechange () : onreadyStatechange () : onReadyStatechange () : onReadyStatechange () : onReadyStatechange () : onReadyStatechange () So n is going to increase by 1 every time you go in, so you’re going to end up with something like this
I'm the code behind n: 1 state:2 state:3 state:4 and the final n is :4Copy the code
Make an asynchronous callback summary
Callbacks are often used in asynchrony, but asynchrony does not require callbacks and can also polling. Callbacks do not necessarily occur in asynchrony. Synchronization can also execute callbacks, such as forEach for arrays
A callback is something you write for someone else to call, pass it as an argument to someone else to call, for example, fn2(fn), let fn2 call the number of fn,
Another example is addEventListener(‘click’,callback), which performs the click to tell the event listener function, and the browser executes the callback.
Another example is setTimeout(callback,1000), which tells the browser to execute the callback function after one second.
Since the asynchronous task can’t get the result directly, we pass a callback function to the asynchronous task. When the asynchronous task completes, we call the callback function, which takes the result as an argument to do some processing.