As we are familiar with “JavaScript is single threaded”, JavaScript execution is executed from top to bottom. The browser allocates only one main thread to JavaScript, which is executed in a task queue. Subsequent tasks wait until the previous task is finished.
– Why single thread?
As a browser scripting language, Javascript is executed in the browser environment, carrying the tasks of direct interaction with users, and must give direct feedback to user operations. If JavaScript is multi-threaded, one thread adds to a DOM node, and another thread edits or deletes it… And so on operation, then the execution result is not conclusive, its role determines it is a single thread.
– Asynchronous processing of JavaScript?
In the execution of JavaScript, we often encounter some need to wait for some value to get, and then hold the value to proceed to the next operation. In the single-threaded event loop model of JavaScript, multiple tasks will be queued for execution, and the next task will be executed after the completion of the previous task, and so on. However, if the execution time of one task is too long, the subsequent tasks must wait in a queue, increasing the execution time of the entire task. For example, a task falls into an “infinite loop”, and subsequent tasks cannot wait for the value of the “infinite loop” task, blocking the execution of the thread, resulting in no response on the page.
Synchronous and asynchronous
synchronous
The code is executed in a top-down order. When one piece of code takes a long time to execute, the rest of the code will wait for it to complete
asynchronous
During code execution, the main process does not need to wait for the execution result of a task that takes a long time, such as network request or image loading. The main process can continue to execute the following code. When this task is complete, the main process is notified, and the main process processes the corresponding program.
Several ways JavaScript handles asynchrony
The callback function
Before ES6, the way we used to write asynchronous code in JavaScript was with callback functions. This kind of code has little impact when the code volume is small, but when the logic becomes large, the disadvantages become obvious, and the callback function nested callback function problem occurs, resulting in callback hell. 1. High coupling, poor code readability 2. Poor late maintainability
ForthFn (function (a) {forthFn(a, function (b) {forthFn(c, c) {forthFn(c, c) function (d) { fifthFn(d, function () { // Do Something }, failureCallback); }, failureCallback); }, failureCallback); }, failureCallback); }, failureCallback);Copy the code
Promise
understand
ES6 introduced a new type Promise, which is essentially an object returned by a function that we can bind to so that we don’t have to pass the callback as an argument to the function in the first place
Three states of promise
- Pending
- This is a big pity, which is sometimes called “resolved” or “resolved”.
- I don’t like it!
Pending is the initial state of a contract. In the pending state, an agreement may be settled (Settled) to represent a successful settlement
This is a big pity, or the state of rejection which represents failure. No matter which state you settle in, it’s irreversible. The status of an agreement does not change once it switches from pending to honored or rejected.
The above definition is from JavaScript Advanced Programming (version 4)
Based on the sample
Let myFirstPromise = new Promise(function(resolve, reject){resolve(...); Reject (...) is called when asynchronous code fails. // In this case, we use setTimeout(...) SetTimeout (function(){resolve(" success! ); // The code works fine! }, 250); }); Myfirstpromise.then (function(successMessage){resolve(...) // The successMessage argument doesn't have to be a string, but console.log("Yay! " + successMessage); });Copy the code
Promise to realize
const processFn = (n) => { return new Promise(resolve => { setTimeout(() => resolve(n + 100), n); }); } const step1 = (n) => { console.log(`step1 with ${n}`); return processFn(n); } const step2 = (n) => { console.log(`step2 with ${n}`); return processFn(n); } const step3 = (n) => { console.log(`step3 with ${n}`); return processFn(n); } function runThis() {console.time("runThis"); const time1 = 300; step1(time1) .then(time2 => step2(time2)) .then(time3 => step3(time3)) .then(result => { console.log(`result is ${result}`); console.timeEnd("runThis"); }); } runThis();Copy the code
async/await
ES8’s Async /await is designed to address the problem of organizing code with asynchronous structures. To do this, ECMAScript extends the function,
Two new keywords have been added to it: async and await.
Async await const processFn = (n) => {return new Promise(resolve => {setTimeout(() => resolve(n + 100), n); }); } const step1 = (n) => { console.log(`step1 with ${n}`); return processFn(n); } const step2 = (n) => { console.log(`step2 with ${n}`); return processFn(n); } const step3 = (n) => { console.log(`step3 with ${n}`); return processFn(n); } const runThis = async () => { console.time("runThis"); const time1 = 300; const time2 = await step1(time1); const time3 = await step2(time2); const result = await step3(time3); console.log(`result is ${result}`); console.timeEnd("runThis"); } runThis();Copy the code