First of all, this article is very long. Please make a cup of coffee and take at least half an hour to savor it.
URL input to the browser to parse a series of events
A lot of big companies like to ask this interview question, what happens when you type in the URL to the page you see? Today we will sum up. In short, there are several processes
- The DNS
- Initiating a TCP Connection
- Sending an HTTP request
- The server processes the request and returns HTTP packets
- The browser parses the rendered page
- Connection terminated.
Let’s look at the details
The DNS
DNS resolution is really the process of finding the resources you need. Suppose you enter www.baidu.com, and this website is not the real address of Baidu, every machine in the Internet has a unique identification of the IP address, this is the key, but it is not easy to remember, a messy string of numbers who remember ah, so you need a url and IP address conversion, that is, DNS resolution. Let’s look at the parsing process
The specific analytical
DNS resolution is a recursive process
www.google.com
com
.
google.com.
www.google.com.
DNS optimization
Now that we know the exact process of parsing, we can see that there are a total of N processes, each process has a certain amount of consumption and time to wait, so we need to find a way to solve this problem!
DNS cache
DNS has multiple levels of cache, sorted by distance from browser: browser cache, system cache, router cache, IPS server cache, root DNS cache, top-level DNS cache, and primary DNS cache.
-
Type :chrome:// DNS/into your Chrome browser and you can see chrome’s DNS cache.
-
The system cache is stored in /etc/hosts(Linux)
DNS Load Balancing
Don’t know if you have to pay attention to such a thing, when you visit baidu.com, each time the response is not the same server (IP address), general big companies have hundreds of thousands of servers to support access, assuming that there is only one server, it’s performance and storage will he be old enough to support such a large number of access? DNS can return the IP address of a suitable machine to the user, for example, according to the load of each machine, the distance between the machine and the user’s geographical location, etc. This process is DNS load balancing
Initiating a TCP Connection
TCP provides a reliable transmission that involves a three-way handshake, a four-way wave, and a more detailed look at TCP provides a connection-oriented, reliable byte stream service. The data format for the header is as follows
Field analysis
-
Source port: The source port and IP address identify the return address of a packet.
-
Destination port: The port specifies the application program interface on the receiving machine.
The source port number and destination port number in the TCP header and the source IP address and destination IP address in the IP packet uniquely determine a TCP connection.
-
Serial number: is the key part of TCP reliable transmission. Ordinal is the ordinal number of the first byte of the data set that the segment is sent from. In a TCP stream, each byte has an ordinal number. For example, if the serial number of a packet segment is 300 and the data portion of the packet segment is 100 bytes, the serial number of the next packet segment is 400. Therefore, sequence numbers ensure the order of TCP transmission.
-
Acknowledgement number: that is, ACK, indicating the next expected byte number, indicating that all data prior to this number has been correctly received. The confirmation number is valid only when the ACK flag is 1. For example, when establishing a connection, the ACK bit of the SYN packet is 0.
-
Header length/data offset: contains 4 bits. It indicates how far the data of the TCP packet is from the start of the TCP packet segment. Since the header may contain optional content, the length of the TCP header is uncertain. If the header does not contain any optional fields, the length is 20 bytes. The maximum length of the 4-bit header field can be 1111, which is 15 in decimal notation, 15*32/8=60, so the maximum length of the header is 60 bytes. The header length is also called data offset because it actually indicates the starting offset of the data area in the packet segment.
-
Reserved: 6 bits, reserved for future use, but should be 0 bits at present.
-
Control bit: URG ACK PSH RST SYN FIN: a total of six flag bits. Each flag bit indicates a control function.
-
Emergency URG: When URG=1, the emergency pointer field is valid. Indicates that there is urgent data in this packet segment
-
ACK: The ACK number field is valid only when ACK=1. According to TCP, ACK must be set to 1 for all packets transmitted after a connection is established.
-
Push PSH: When two application processes are communicating interactively, sometimes the application on one side wants to receive a response immediately after typing a command, so PSH=1 is used.
-
Reset RST: If RST is 1, it indicates that a serious error occurs in the TCP connection. You must release the connection and re-establish the connection.
-
Synch SYN: Used to synchronize serial numbers when a connection is established. If SYN=1, ACK=0, it indicates that the packet is a connection request packet. If SYN=1, ACK=1 is allowed in the response packet.
-
Terminate the FIN: Releases the connection. If the FIN value is 1, the sender finishes sending data and wants to release the packet.
-
-
Window: The sliding window size is used to inform the sender of the cache size of the receiver, so as to control the rate at which the sender sends data and achieve flow control. The window size is a 16bit field, so the maximum window size is 65535.
-
Checksum: The parity check. The checksum is calculated in 16-bit characters for the entire TCP packet segment, including the TCP header and TCP data. It is calculated and stored by the sender and verified by the receiver.
-
Emergency pointer: The emergency pointer is valid only when the URG flag is set to 1. The emergency pointer is a positive offset that is added to the value in the ordinal field to indicate the ordinal number of the last byte of the emergency data. TCP emergency mode is a way for the sender to send emergency data to the other end.
-
Options and Padding: The most common optional field is the Maximum Segment Size (MSS), which is specified by each connector in the first Segment of the communication (the Segment where the SYN flag is set to 1 for connection establishment). This parameter indicates the Maximum Segment length that the local end can accept. The option length does not have to be a multiple of 32 bits, so padding bits are added, that is, adding an extra zero to the field to ensure that the TCP header is a multiple of 32.
-
Data part: The data part of the TCP packet segment is optional. When a connection is established and when a connection is terminated, only the TCP header is exchanged. If one party has no data to send, the header without any data is also used to acknowledge the received data. In many cases of processing timeouts, a segment of the message without any data is also sent.
Note that: (A) Do not confuse the acknowledgement sequence Ack with the Ack in the flag bit. (B) Confirming party Ack= initiating party Req+1, both ends are paired.
Three-way handshake
First handshake:
The client sends a SYN packet (Seq= X) to the server and enters the SYN_SEND state.
Second handshake:
After receiving a SYN packet, the server must acknowledge the client’s SYN (ACK = X +1) and send a SYN packet (Seq= Y). In this case, the server enters the SYN_RECV state.
Third handshake:
After receiving the SYN+ACK packet from the server, the client sends an ACK packet (ACK = Y +1) to the server. After the packet is sent, the client and the server enter the ESTABLISHED state and complete the three-way handshake.
The packet transmitted during the handshake does not contain data. After three handshakes, the client and server start data transmission. Ideally, once a TCP connection is established, it is maintained until either of the communicating parties voluntarily closes the connection.
Why do you use the three-way handshake? Is it ok to use the two-way handshake? Four times?
The connection is established using client-server mode, assuming that host A is the client and host B is the server.
The three-way handshake is used to prevent the invalid connection request segment from suddenly being sent to host B and causing an error. Invalid connection request packet segment: Host A sends A connection request to host B again after A period of time because the connection request is not acknowledged by host B. The connection request is successfully established and data is transmitted in sequence. Consider A special case, host A sends A connection request is not lost for the first time, but because the network nodes lead to delay to host B, thought is to host A and host B launched A new connection, so the host B agree to connect, and sent back to the host A confirmation, but now host A can’t ignore, host B I have been waiting for the host to send data, Resources on host B are wasted.
Using a two-handshake will not work because of the special case of a failed connection request described above. In the three-way handshake, both the client and server send syn and ack packets. If both parties can receive ack packets after sending syn packets, the communication is ready.
Why not four handshakes? You should be aware of the famous blue and Red Army agreement in communication. This example shows that communication cannot be 100% reliable, and the above three handshakes have already done the preparation work for communication. Additional handshakes do not significantly improve reliability, and are not necessary.
Four times to wave
After data transfer is complete, both parties can release the connection. Initially, both the client and the server are in the ESTABLISHED state, assuming that the client is actively shut down and the server is passively shut down.
First wave:
The client sends a FIN to shut down the client-to-server data transfer. That is, the client tells the server: I will not send you any more data (of course, the client will resend the data sent before the FIN packet if it does not receive the corresponding ACK packet), but the client can still accept the data. If FIN=1 and the sequence number is seq=u (equal to the sequence number of the last byte of the previously transmitted data plus 1), the client enters fin-WaIT-1 (terminate WAIT 1) state. According to TCP, FIN packets consume a sequence number even if they do not carry data.
Second wave:
After receiving a FIN packet, the server sends an ACK with its own SEQUENCE number (SEQ) and confirms that the received sequence number is +1 (the same as SYN, one FIN occupies one sequence number). At this point, the server enters close-wait state. The TCP server notifies the higher-level application process that the client is released from the direction of the server. This state is half-closed, that is, the client has no data to send, but if the server sends data, the client still accepts it. This state also lasts for a period of time, i.e. the duration of the close-wait state.
At this point, the client enters the fin-WaIT-2 state and waits for the server to send a connection release message (it also needs to accept the last data sent by the server before doing so).
Third wave:
The server sends a FIN to shut down the data transfer from the server to the client, telling the client that my data has also been sent and I will not send you any more data. Since the server is in the semi-closed state, it is likely to send some more data, assuming that the serial number is SEq = W. At this point, the server enters the last-ACK state, waiting for the client to confirm.
Fourth wave:
After receiving the FIN, the active shutdown party sends an ACK to the passive shutdown party, confirming that the sequence number is +1. In this case, the client enters the time-wait state. Note that the TCP connection is not released at this time, and the client can enter the CLOSED state only after 2∗MSL (maximum packet segment life) and the corresponding TCB is revoked.
The server enters the CLOSED state immediately after receiving an acknowledgement from the client. Similarly, revoking the TCB terminates the TCP connection. As you can see, the server ends the TCP connection earlier than the client.
At this point, complete the four waves.
Why does the client end up waiting for 2MSL?
MSL (Maximum Segment Lifetime) : TCP allows different implementations to set different MSL values.
First, ensure that the client sends the final ACK packet to reach the server, because the ACK packet may be lost, standing in the server’s perspective, I have already sent the FIN + ACK message request disconnect, the client also did not give me response, should be I send the request of the disconnect message it did not receive, then the server will send a again, The client receives the retransmitted message within the 2MSL period, responds with a message, and restarts the 2MSL timer.
Second, prevent “invalid connection request message segment” as mentioned in “three-way handshake” from appearing in this connection. After the client sends the last acknowledgement message, in this 2MSL time, all the message segments generated during the duration of the connection can be removed from the network. In this way, the new connection does not contain the request packets of the old connection.
Why is establishing a connection a three-way handshake, but closing a connection a four-way wave?
During connection establishment, the server receives a SYN packet in LISTEN state and sends the ACK and SYN packets to the client. And close connection, the server receives the other side of the FIN message, just said to each other can no longer send data but also receives the data, and the oneself also is not necessarily all data are sent to each other, so their can immediately shut down, also can send some data to each other, then send the FIN message now agreed to close the connection to the other side, therefore, The ACK and FIN are usually sent separately, resulting in an extra ACK.
Sending an HTTP request
The HTTP port is 80/8080 and the HTTPS port is 443
The process of sending an HTTP request is to construct an HTTP request message and send it over TCP to a specified port on the server. A request message consists of a request line, a request header, and a request body.
The request line
The format of the Request line is Method request-URL http-version CRLF eg: GET index. HTML Common HTTP/1.1 methods are GET,POST, PUT, DELETE, OPTIONS, and HEAD.
Common request method differences
Here we show the difference between POST and GET
Common differences
- GET is harmless when the browser falls back, while POST resubmits the request.
- The URL generated by GET can be bookmarked, but not by POST.
- GET requests are actively cached by browsers, whereas POST requests are not, unless set manually.
- GET requests can only be url encoded, while POST supports multiple encoding methods.
- GET request parameters are retained in browser history, while parameters in POST are not.
- GET requests pass parameters in the URL with length limits, whereas POST does not.
- GET accepts only ASCII characters for the data type of the argument, while POST has no restrictions.
- GET is less secure than POST because parameters are exposed directly to the URL and therefore cannot be used to pass sensitive information.
- The GET argument is passed through the URL, and the POST is placed in the Request body.
Note that you can also hide the body in GET and the argument in POST
Key difference between
GET produces one TCP packet, and POST produces two TCP packets.
The details are:
-
For GET requests, the browser sends both HTTP headers and data, and the server responds with 200(return data).
-
For POST, the browser sends a header, the server responds with 100 continue, the browser sends data, and the server responds with 200 OK (returns data).
Note that not all browsers send packets twice, Firefox sends packets once
The request header
The request header allows the client to pass additional information about the request and the client itself to the server.
Request body
When using POST, PUT, and other methods, the client is usually required to pass data to the server. This data is stored in the request body. The request header contains some information related to the request body. For example, Web applications today usually use Rest architecture, and the requested data format is json. You need to set content-Type: application/json.
More important things -HTTP caching
HTTP belongs to the client cache. We often think of the browser as having a cache database, which is used to store static files. We will briefly introduce HTTP cache in the following aspects
- Rules for caching
- Caching scheme
- Advantages of caching
- Request execution for different refreshes
Rules for caching
Cache rules are classified into mandatory cache and negotiated cache
Mandatory cache
When the cache database has the data that the client needs, the client directly takes the data out of it and uses it (if the data is not invalid). When the cache server does not need the data, the client will request the server.
Negotiate the cache
Also known as contrast caching. The client will first get a cached identifier from the cache database, and then verify to the server whether the identifier is invalid. If not, the server will return 304, so that the client can directly go to the cache database to retrieve data. If not, the server will return new data
The mandatory cache has a higher priority than the negotiated cache. If both caches exist and the mandatory cache hits the target, the negotiated cache does not validate the identity.
Caching scheme
The above gives us an idea of how caching works, but how does the server determine if the cache is invalidated? We know that when a browser interacts with a server, it sends request data and response data, which we call HTTP packets. The packet contains the header and the body. The cache-related rule information is contained in the header. The content in the BOBY is what the HTTP request actually transmits. An example of HTTP header is as follows:
Mandatory cache
For mandatory caching, the header in the server response is indicated by two fields — Expires and cache-Control.
Expires
The value of Exprires is the data expiration time returned by the server. When the request time on a second request is less than the returned time, the cached data is used directly. Because server and client times can be inconsistent, which can lead to errors in Cache hits, on the other hand, Expires is a product of HTTP1.0, so cache-control is now mostly used instead.
Cache-Control
Cache-control has many attributes, each of which has different meanings.
- Private: The client can cache
- Public: Both client and proxy servers can cache
- Max-age =t: The cache contents will be invalid in t seconds
- No-cache: A negotiated cache is required to validate cached data
- No-store: All content is not cached.
Negotiate the cache
Negotiation caches require comparison to determine whether caches can be used. The first time the browser requests data, the server responds with the cache id along with the data to the client, which backs it up to the cache. When requested again, the client sends the cached identity to the server, which determines based on this identity. If not, the 304 status code is returned and the browser can use the cached data directly.
For negotiated caches, the cache identity needs to be understood, and we’ll focus on two caching schemes for it.
Last-Modified
Last-modified: When the server responds to a request, it tells the browser when the resource was Last Modified.
-
If-modified-since: The request header contains this field when the browser requests the server again, followed by the last modification time obtained in the cache. The server receives the request with if-modified-since, and compares it with the last Modified time of the requested resource. If the request is consistent, 304 and the response header are returned. The browser only needs to retrieve the information from the cache. Whether a file has been modified since a certain point in time
- If it is: then start transmitting the response as a whole, and the server returns: 200 OK
- If Not Modified: then simply transmit the response header and the server returns: 304 Not Modified
-
If-unmodified-since: Indicates whether the file has not been modified Since a point in time
- If not modified: Start ‘continue’ transfer file: server returns: 200 OK
- If the file is modified: No feed, the server returns 412 Preprocessing failed
The difference between these two is that one is downloaded after modification and the other is downloaded without modification.
Last-modified is not particularly good, because if on the server a resource is Modified but its actual contents have not changed at all, the entire entity is returned to the client because the last-Modified time does not match (even if the client has an identical resource in its cache). To address this issue, HTTP1.1 introduced Etag.
Etag
Etag: This field tells the browser the unique identity of the current resource generated by the server when the server responds to a request (the generation rule is determined by the server)
-
If-none-match: If the browser requests the server again, the header of the request packet contains this field, and the following value is the identifier obtained from the cache. After receiving the secondary packet, the server compares if-none-match with the unique identifier of the requested resource.
- If no, the resource has been modified. The status code 200 is returned in response to the entire resource content.
- If yes, the resource does not need to be modified. In this case, the browser responds to the header and directly obtains data from the cache. Return status code 304.
However, in practical applications, Etag is seldom used because the calculation of Etag is obtained by algorithm, which will occupy the computing resources of the server side. All the resources of the server side are precious.
Advantages of caching
- Redundant data transmission is reduced and broadband traffic is saved
- Reduce the server burden, greatly improve the performance of the site
- This makes it faster for clients to load web pages, which is why HTTP caches are client caches.
Request execution for different refreshes
Enter the URL in the browser address bar and press Enter
- The browser has found the file in the cache, so it doesn’t need to go to the cache. (the) fastest
F5
- F5 tells the browser, don’t be lazy, at least go to the server to see if the file has expired. The browser nervously sends a request with if-modify-since.
Ctrl+F5
- Tell the browser, you first your cache of this file to me delete, and then go to the server to request a complete resource file down. The client then completes the force-update operation.
The server processes the request and returns HTTP packets
It processes TCP connections, parses HTTP, and encapsulates HTTP Request objects based on packet formats for upper-layer use. This part of the work is generally carried out by Web servers. The Web servers I have used include Tomcat, Nginx and Apache, etc. HTTP packets are also divided into three parts: status code, response header and response packet
Status code
The status code consists of three digits. The first number defines the category of the response and has five possible values:
-
1XX: indicates that the request has been received and processing continues.
-
2xx: success – The request is successfully received, understood, or accepted.
-
3xx: Redirect – Further action must be taken to complete the request.
-
4XX: client error – The request has a syntax error or the request cannot be implemented.
-
5xx: Server side error – The server failed to fulfill a valid request. Usually encountered more common status code :200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500
Common status code differences
200 success
The request succeeds, and usually the server provides the required resources.
204 no content
The server successfully processed the request, but did not return anything.
301 Permanent Move
The requested page has been permanently moved to the new location. When the server returns this response (a response to a GET or HEAD request), it automatically forwards the requester to the new location.
302 Temporary Move
The server currently responds to requests from web pages in different locations, but the requester should continue to use the original location for future requests.
304 unmodified
The requested page has not been modified since the last request. When the server returns this response, the web page content is not returned.
400 Error request
The server does not understand the syntax of the request.
401 unauthorized
The request requires authentication. The server may return this response for a web page that requires login.
403 ban
The server rejected the request.
404 not found
The server could not find the requested page.
422 cannot be processed
The request was well-formed, but could not be responded to due to semantic errors
500 The server has an internal error
The server encountered an error and could not complete the request.
Response headers
Common response header fields are: Server, Connection… .
The response message
This is where the HTML,CSS, and JS files you request from the server are stored
The browser parses the rendered page
Webkit
- Parsing HTML to form a DOM tree
- Parses the CSS to form the CSSOM tree
- Combine DOM tree and CSSOM tree to form render tree
- The process of the browser rendering and drawing the page involves two important concepts: backflow and redraw. DOM nodes exist in a box model and the browser needs to calculate position and width etc. This process is called backflow. Once the page’s width, height, size, color and other attributes are determined, the browser begins to draw the content, a process called redraw. The browser must go through these two processes when opening the page, but this process is very, very, very performance consuming, so we should minimize page backflow and redraw
Reflux redraw for performance optimization
backflow
When the size, structure, or attributes of some or all of the elements in the Render Tree change, the process by which the browser rerenders some or all of the document is called reflux.
Operations that cause backflow:
- Page first render
- The browser window size changed. Procedure
- The size or position of the element changed
- Element content changes (number of words or image size, etc.)
- Element font size changes
- Add or remove visible DOM elements
- Activate CSS pseudo-classes (such as: :hover)
- Query some properties or call some methods
Some common properties and methods that cause backflow:
ClientWidth, clientHeight, clientTop, clientLeft
OffsetWidth, offsetHeight, offsetTop, offsetLeft
ScrollWidth, scrollHeight, scrollTop, scrollLeft
ScrollIntoView (), scrollIntoViewIfNeeded ()
getComputedStyle()
getBoundingClientRect()
scrollTo()
redraw
When a change in the style of an element in a page does not affect its position in the document flow (e.g., color, background-color, visibility, etc.), the browser assigns the new style to the element and redraws it, a process called redraw.
To optimize the
CSS
- Avoid table layouts.
- Change the class at the very end of the DOM tree whenever possible.
- Avoid setting multiple inline styles.
- Apply the animation to an element whose position attribute is absolute or fixed.
- Avoid USING CSS expressions (such as calc()).
JavaScript
- To avoid manipulating styles too often, it is best to override the style property once, or define the style list as class and change the class property once.
- To avoid frequent DOM manipulation, create a documentFragment, apply all DOM manipulation to it, and finally add it to the document.
- You can also set display: None to the element and display it after the operation is complete. Because DOM operations on elements with the display attribute none do not cause backflow and redraw.
- Avoid frequently reading properties that cause backflow/redraw, and if you do need to use them more than once, cache them in a variable.
- Use absolute positioning on elements with complex animations to keep them out of the document stream, which would otherwise cause frequent backflow of parent elements and subsequent elements.
JS parsing
JS parsing is done by the browser’s JS engine. Because JavaScript is a single process, that is to say, can only do one thing at a time, do the things when other things are in line, but some people more time-consuming (such as IO operations), so the task is divided into synchronous task and asynchronous tasks, all on the main thread synchronization task execution, execution stack, and asynchronous task waiting, When the execution stack is empty, the asynchronous task is checked to see if there is anything to do, and then the main thread is extracted to execute. This Loop is formed by the Event Loop
Event Loop
Let’s take a look at some code
setTimeout(function(){
console.log('Timer's on.')}); new Promise(function(resolve){
console.log('Execute for loop now');
for(var i = 0; i < 10000; i++){
i == 99 && resolve();
}
}).then(function(){
console.log('Execute the then function')}); console.log('End of code execution');
Copy the code
I think we should all know the results. I’ll focus on JavaScript parsing, but I’ll talk about promises in the next section
JavaScript
JavaScript is a single-threaded language. Although the Web-worker proposed in H5 can simulate the implementation of multi-threading, it is still single-threaded in nature. It is nonsense to say that it is multi-threaded.
Event loop
Since it is a single thread, the execution of each event has to have a sequence, for example, you go to the bank to withdraw money, the front people are doing, the back people have to wait, if the front people do one or two hours, I estimate that the back people are crazy, therefore, the browser JS engine processing JavaScript is divided into synchronous tasks and asynchronous tasks
- Synchronous and asynchronous tasks go to different execution “places”, synchronous tasks go to the main thread, asynchronous tasks go to the Event Table and register functions.
- When the specified Event completes, the Event Table moves this function to the Event Queue.
- If the tasks in the main thread are empty after execution, the Event Queue will read the corresponding function and enter the main thread for execution.
- This process is repeated over and over again, known as an Event Loop.
The js engine has a monitoring process that continuously checks to see if the main thread stack is empty, and if it is, checks the Event Queue to see if there are any functions waiting to be called. You’ll probably have some idea what the event loop is, but it’s not that simple. Usually we’ll see Promise, setTimeout, process.nexttick (), and you and I will be confused.
In addition to synchronous tasks and asynchronous tasks, we also divide them into macro tasks and micro tasks
- Macro-task: includes the entire code script, setTimeout, and setInterval
- Micro-task: Promise, process.nextTick Different tasks will enter different task queues for execution. After the JS engine starts working, the first loop is started in the macro task (
Script goes first, but I like to pull it out and just call it on the stack
), when the main thread execution stack all tasks are cleared, go to the microtask to see, if there are tasks waiting to be executed, execute all the microtasks (in fact, push its callback function into the execution stack to execute), and then go to the macro task to find the first queued task to execute. Execute this task and then go to the main thread to perform tasks (such as console.log(“hello world”)), then go to the microtask when the stack is cleared, and so on.
Microtasks are executed in full, while macro tasks are executed one by one
Let’s look at a piece of code
setTimeout(function() {
console.log('setTimeout');
})
new Promise(function(resolve) {
console.log('promise');
}).then(function() {
console.log('then');
})
console.log('console');
Copy the code
Let’s see how it works
- The first round
- This code goes into the main thread
- When a setTimeout is encountered, register its callback function and distribute it to the macro task
- The second round
- When a Promise is encountered, the new Promise is executed immediately (this is not explained, AND I will introduce it in a future article) and output
promise
Encountered,then
And distribute it to microtasks
- When a Promise is encountered, the new Promise is executed immediately (this is not explained, AND I will introduce it in a future article) and output
- In the third round
- encounter
console.log("console")
, direct outputconsole
- encounter
- The fourth round of
- The main thread execution stack has been emptied, so let’s go to the micro task, execute the then function, and print
then
- The main thread execution stack has been emptied, so let’s go to the micro task, execute the then function, and print
- The fifth round
- So the micro task is done, look at the macro task, it has a setTimeout, output
setTimeout
, the whole execution is complete. The specific implementation process is roughly like this, I may have negligence, but also hope to correct.
Let’s look at another piece of complicated code
- So the micro task is done, look at the macro task, it has a setTimeout, output
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')})setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')})})Copy the code
So let’s analyze it
- The whole script enters the main thread, encountered
console.log('1')
, direct output - encounter
setTimeout
, dispatches its callback function to the macro task event queue, temporarily labeled setTimeout1 - encounter
process.nextTick()
, dispatches its callback function to the microtask event queue, marked asprocess.nextTick1
(This is a bit different, I generally think that process.nexttick () is pushed to the bottom of the stack as the last task on the stack) - When you encounter a Promise, execute immediately and print it
7
, a queue of microtask events distributed by the THEN function, labeled Promise1. - When a setTimeout is encountered, its callback function is dispatched to the microtask event queue, labeled setTimeout2.
- Now it’s printed
1, 7
The event queues of macro tasks and micro tasks are as follows
Let’s move on
- Now that the main thread execution stack is cleared, go to the microtask and see that there are two events waiting to be executed because the queue is first-in, first-out
process.nextTick1
And the output6
, then executePromise1
And the output8
.
At this point, the first loop has finished, printing 1,7,6,8, and the second loop starts with setTimeout1 for the macro task
- encounter
console.log('2')
Execute the output. - encounter
process.nextTick()
, distributes its callback function to the microtask, marked asprocess.nextTick2
And meetPromise
, execute immediately, output4
, push the THEN function to the microtask event queue, marked asPromise2
- A task to this macro task completes, and the output is displayed
2, 4
Take a look at the event queue
- Go to micromission. We’ll deal with it first
process.nextTick2
And the output3
“, and then executePromise2
And the output5
. The second cycle is complete. So now we have a total output1,7,6,8,2,4,3,5
- from
setTimeout2
Start the third cycle, directly output first9
Encountered,process.nextTick()
, dispatches its callback function to the microtask event queue, marked asprocess.nextTick3
“, and encountered the disgusting Promise, immediately execute the output11
, distribute the THEN function to the microtask, flagged as Promise3. - Do a micromission and see what else happens
There are still events. What can I do? Execute and print
10, 12
. At this point, all tasks are completed, and the output sequence is1,7,6,8,2,4,3,5,9,11,10,12
.
Note that the result of this code execution may vary depending on, for example, node.
That’s all I want to say. I don’t know if you understand
conclusion
This article from a simple question pulled out a lot of front-end engineers must learn is also very important things, but because of my low level, many places are overmentioned, even some places have mistakes, I hope colleagues to correct and criticize.