This is the 19th day of my participation in the August Wenwen Challenge.More challenges in August

1. Introduction to asynchronous requests

Js is a language born for the browser. Now, JS is not only run on the browser, but also run on the server, like Node. Js is originally designed to be single-threaded, which means that it will execute line by line and wait for the above code to finish executing. In other words, it can only do certain things at a certain time and block the execution of other code

Knowing why asynchrony occurs in javascript, what can we do about it?

2. Solution 1: Ajax

Since JavaScript runs single-threaded, is XMLHttpRequest really asynchronous after a connection? The request is actually asynchronous, but it is requested by a new thread of the browser (see figure above). When the state of the request changes, if the callback has been set previously, the asynchronous thread generates the state change event and puts it in the JavaScript engine’s processing queue. When the task is processed, The JavaScript engine always runs single-threaded callback functions, specifically functions set by onReadyStatechange.

Understanding how a JavaScript engine works is important, especially when a large number of asynchronous events occur (in succession) to improve the efficiency of your code. For a normal Ajax request, sending a JSON request with XHR would look something like this:

var xhr =  new XMLHttpRequest();

 xhr.open("GET", url);

 xhr.responseType =  'json';

 xhr.onload =  function(){

   console.log(xhr.response);

};

 xhr.onerror =  function(){

console.log("error")

}

xhr.send();
Copy the code

In theory, if the ajax asynchronous request, asynchronous callback function of it is in a single thread, the callback function will not be other threads “blocking” and carried out smoothly, namely after 1 second, it callback execution pop-up ajax, but it’s actually not the case, the callback function can’t perform, because the browser again feign death because death cycle.

According to the above two examples, the summary is as follows:

  1. JavaScript engines are single-threaded, and browsers have only one and only one thread running a JavaScript program at any given time.
  2. It also makes sense for the JavaScript engine to run with a single thread, which simplifies the problem by eliminating the complexity of thread synchronization.

3. Solution 2: Fetch

The way fetch is implemented:

  fetch(url).then(function(response){ 
     return response.json(); 
 }).then(function(data){ 
     console.log(data) 
}).catch(function(e){ 
     console.log("error") 
}) 
Copy the code

The main advantages of FETCH are

  • Syntax concise, more semantic
  • Standards-based Promise implementation that supports async/await
  • Isomorphism convenient

But it also has its disadvantages

  • The FETCH request does not contain cookies by default and needs to be setfetch(url, {credentials: 'include'})
  • The server does not reject 400,500 error codes, and the fetch is rejected only when network errors such as these cause the request to fail.

4. Solution three: Promise

When writing asynchronously in Ajax, it’s easy to fall into callback hell and make your code much less readable. Promises can make code more elegant.

Encapsulate Promise based XHR

Function ajax (method,url) {return new Promise(function (resolve) {var XMLHTTP = new XMLHttpRequest () / / create asynchronous request / / asynchronous request state change will perform this function when XMLHTTP. The onreadystatechange = function () {/ / status = = 200 ReadyState == 4 && xmlhttp.status == 200) {resolve(json.parse (xmlhttp.responsetext)) // Xmlhttp.open (method,url) // Use the GET method to GET xmlhttp.send() // send an asynchronous request})}Copy the code

5. Solution 4: async/await

Writing asynchronous code feels as good as writing synchronous code after using await. Await can be followed by a Promise object that waits for a Promise resolve() to proceed. If a Promise is rejected () or an exception is thrown, the Promise will be treated by a try… Catch caught.

ES7’s ASNYC /await claims to be the ultimate solution to asynchrony, letting us write asynchronous code synchronously so it looks cleaner and more logical.

try{ 
 let response = await fetch(url); 
 let data = await response.json(); 
 console.log(data); 
} catch(e){ 
 console.log("error") 
}
Copy the code

6. Three threads for the browser

Browsers are multithreaded and work with each other under kernel control to keep them in sync. A browser implements at least three resident threads: JavaScript engine threads, GUI rendering threads, and browser event-firing threads (UI threads).

1. Javascript engines are event-driven single thread execution. The JS engine always waits for the arrival of the task in the Event loop and then processes it (it will fetch the task from the task queue only after the current function execution stack finishes). The browser has only one JS thread running the JS program at any one time. 2. The UI rendering thread is responsible for rendering the browser interface, which is executed when the interface needs to be repainted or reflow due to some action. However, GUI rendering thread and JS engine are mutually exclusive. GUI thread will be suspended when JS engine executes, and JS operations on the page, namely GUI updates, will also be saved in a queue until JS engine is idle to be executed. This is JS blocking page loading. 3. Event triggering thread. When an event is triggered, the thread will add the event to the end of the task queue and wait for the JS engine to process it. These events can be added by calling setTimeout/ Ajax from the block of code currently executed by the JavaScript engine, or they can be added by other threads in the browser such as mouse clicks. However, due to the single-threaded nature of JS, all these events have to queue up for the JS engine to process.Copy the code

Javascript waits for the main thread to empty before checking to see if the child thread is calling back content. Asynchronous tasks are executed in a variable order, depending on the speed of return.

7. Two asynchronous apis, setTimeout and setInterval

setTimeout(function(){ /* Some long block of code ... */ setTimout(arguments.callee,10); }, 10); setInterval(function(){ /* Some long block of code ... * /}, 10);Copy the code

The two programs look the same at first glance, but they are not. The setTimeout code is executed at least once every 10ms; However, setInterval will attempt to execute every 10ms regardless of the execution status of its callback function.

Let’s summarize:

- The JavaScript engine has only one thread, forcing asynchronous events to queue for execution. - setTimeout and setInterval are fundamentally different when executed asynchronously. - If a timer is blocked, it will be delayed until the next executable point (which may take longer than expected) - setInterval's callbacks may be executed continuously, without interval (if the callback execution takes longer than the predetermined wait value)Copy the code

SetInterval:

When using setInterval(), the timer code is added to the queue only if there are no other code instances of the timer. Two issues should be noted:

  1. Certain intervals will be skipped;
  2. The interval between code execution of multiple timers may be smaller than expected. The difference between setTimeout and setsetInterval can be used as an example.

Eight,

All asynchronous requests take advantage of the browser timer