Principle of this paper:

JavaScript is single-threaded, and setTimeout puts code at the end of the thread.

Promises are established and executed in the same order as normal code.

A Promise does not trigger a subsequent THEN until the state changes to resolve


  1. It will take about 15-25 minutes to finish this article
  2. Pre-knowledge of this article: basic JS, Promise objects, ES6 and other basic knowledge
  3. Reading Difficulty: Elementary
  4. All the code and output of this article are written out, so you can browse the article without using a compiler


If you know the results of the following code, this article is of limited benefit to you

const showNode = document.getElementById("show");

showNode.innerHTML += "normal | ";

let promise = new Promise((resolve, reject) = > {
  showNode.innerHTML += "promise | ";
  setTimeout((a)= > { resolve("then |"); }, 0)
})

promise.then((res) = > {
  setTimeout((a)= > { showNode.innerHTML += 'then wait | ' }, 0)
  showNode.innerHTML += res;
  return " next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
  return " next next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
})

setTimeout((a)= > { showNode.innerHTML += "wait | " }, 0)

/ / output: normal | promise | then | next then | next next then | wait |
// then wait |
Copy the code







The text start

Javascript engine single thread mechanism

  • To be clear, JavaScript engines are single-threaded

  • JavaScript is single-threaded and cannot execute multiple pieces of code simultaneously. While a piece of code is executing, all subsequent tasks must wait, forming a task queue. Fetching the next task from the queue once the current task has finished is often called “blocking execution.”

  • Asynchronous code is executed only if there is no synchronous code to execute in the JS thread

The js thread knowledge can be moved to the JS single thread and setTimeout execution principle


The execution flow of promise,then and setTimeout

Execute the normal order -> then -> setTimeouts -> THEN setTimeouts


Note 1: showNode is the element I used to get the HTML and display it directly on the page, replacing console.log

Note 2: For example code, new code or modified code, corresponding comments will be added at the end of the code


Normal execution: The command is executed from top to bottom

Environment 1 plain code comes before promise

showNode.innerHTML += "normal | ";

let promise = new Promise((resolve, reject) = > {
  showNode.innerHTML += "promise | ";
})

/ / output: normal | promise |
Copy the code

Environment 2 Promises before normal code

let promise = new Promise((resolve, reject) = > {
  showNode.innerHTML += "promise | ";
})
  
showNode.innerHTML += "normal | ";

/ / output: promise | normal |
Copy the code
  • Promises are executed immediately after they are made, from top to bottom in the normal code execution order


And then: After the normal execution is complete, then is executed

Environment 3 adds then

let promise = new Promise((resolve, reject) = > {
  showNode.innerHTML += "promise | ";
  resolve("then |")                             // Add new code
})

promise.then((res) = > {                         // Add new code
  showNode.innerHTML += res;                    // Add new code
})                                              // Add new code

showNode.innerHTML += "normal | ";              // Code location changes

/ / output: promise | normal | then |
Copy the code
  • When the state of the promise is changedpendingintofulfilledAfter, corresponding to usethenWill be executed.
  • Normally executed code is executed in the first batch, then in the second batch, and then when the first batch is complete


External setTimeout: executes after then

Environment 4 added a setTimeout to the global

setTimeout((a)= > { showNode.innerHTML += "wait | " }, 0)  // Add new code

let promise = new Promise((resolve, reject) = > {
  showNode.innerHTML += "promise | ";
  resolve("then |")
})

promise.then((res) = > {
  showNode.innerHTML += res;
})

showNode.innerHTML += "normal | ";

/ / output: promise | normal | then | wait |
Copy the code
  • SetTimeout pushes code execution to the end of the thread, in the third batch


Environment 5 more then

let promise = new Promise((resolve, reject) = > {
  showNode.innerHTML += "promise | ";
  resolve("then |")
})

promise.then((res) = > {
  showNode.innerHTML += res;
  return " next then | ";                       // Add new code
}).then((res) = > {                              // Add new code
  showNode.innerHTML += res;                    // Add new code
  return " next next then | ";                  // Add new code
}).then((res) = > {                              // Add new code
  showNode.innerHTML += res;                    // Add new code
})

showNode.innerHTML += "normal | ";

setTimeout((a)= > { showNode.innerHTML += "wait | " }, 0)

/ / output: promise | normal | then | next then | next next then | wait |
Copy the code
  • As mentioned earlier, the normal sequence of code execution is in the first batch, then in the second batch, setTimeout in the third batch,
  • Execute the second batch after the completion of the first batch, execute the third batch after the completion of the second batch


In the promiseSetTimeout: After using setTimeout, all are carried to the end of the process and printed in the normal code order

Environment 6 Include setTimeout in the promise

let promise = new Promise((resolve, reject) = > {
  // Add new code
  setTimeout((a)= > { showNode.innerHTML += "promise wait | "; }, 0) 
  showNode.innerHTML += "promise | ";
  resolve("then |")
})

promise.then((res) = > {
  showNode.innerHTML += res;
  return " next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
  return " next next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
})

showNode.innerHTML += "normal | ";

setTimeout((a)= > { showNode.innerHTML += "wait | " }, 0)

/ / output: promise | normal | then | next then | next next then |
// promise wait | wait |
Copy the code
  • Because the Promise was in the first batch, the setTimeout set in the Promise was referred to in the third batch
  • In the third batch, the process is also executed from top to bottom


Environment 7 External setTimeout precedes setTimeout in the Promise

showNode.innerHTML += "normal | ";

setTimeout((a)= > { showNode.innerHTML += "wait | " }, 0)  // Code location changes

let promise = new Promise((resolve, reject) = > {
  setTimeout((a)= > { showNode.innerHTML += "promise wait | "; }, 0)  
  showNode.innerHTML += "promise | ";
  resolve("then |")
})

promise.then((res) = > {
  showNode.innerHTML += res;
  return " next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
  return " next next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
})

/ / output: normal | promise | then | next then | next next then | wait |
// promise wait |
Copy the code


Environment 8 promose wraps Resolve with setTimeout

showNode.innerHTML += "normal | ";

setTimeout((a)= > { showNode.innerHTML += "wait | " }, 0)

let promise = new Promise((resolve, reject) = > {
  showNode.innerHTML += "promise | ";
  setTimeout((a)= > { resolve("then |"); }, 0)     // Code changes
})

promise.then((res) = > {
  showNode.innerHTML += res;
  return " next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
  return " next next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
})

/ / output: normal | promise | wait | then | next then | next next then |
Copy the code
  • Again, think in terms of batches, setTimeout is set in the first batch, and the function executed in it is referred to in the third batch.
  • Promise only state changesfulfilledBefore it triggers the correspondingthen
  • Will control the state in the first batchresolve()To mention the third batch is to change the original second batchthenAll the implementation is referred to the third instalment.
  • The first is code executed in normal order, the second is empty, and the third is executed from top to bottom.


Environment 9 moves the setTimeout outside the Promise down

showNode.innerHTML += "normal | ";

let promise = new Promise((resolve, reject) = > {
  showNode.innerHTML += "promise | ";
  setTimeout((a)= > { resolve("then |"); }, 0)     
})

promise.then((res) = > {
  showNode.innerHTML += res;
  return " next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
  return " next next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
})

setTimeout((a)= > { showNode.innerHTML += "wait | " }, 0) // Code location changes

/ / output: normal | promise | then | next then | next next then | wait |
Copy the code


SetTimeout in environment 10 then

showNode.innerHTML += "normal | ";

let promise = new Promise((resolve, reject) = > {
  showNode.innerHTML += "promise | ";
  setTimeout((a)= > { resolve("then |"); }, 0)
})

promise.then((res) = > {
  // Add new code
  setTimeout((a)= > { showNode.innerHTML += 'then wait | ' }, 0)  
  showNode.innerHTML += res;
  return " next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
  return " next next then | ";
}).then((res) = > {
  showNode.innerHTML += res;
})

setTimeout((a)= > { showNode.innerHTML += "wait | " }, 0)

/ / output: normal | promise | then | next then | next next then | wait |
// then wait |
Copy the code
  • First batch: Execute code in normal order.
  • Second batch: empty
  • Third batch: the end of the thread mentioned by setTimeout
  • Batch 4: referred to the end of the thread by setTimeout in then


This is the end of the article

This article according to their own understanding, according to the idea of “batch” to explain, hoping to make the article appears more easy to understand.

If there is something wrong, please point it out in the comments section or send me a private message.

Your advice will make my next article more exciting


Thank you for watching