Related learning recommendations: javascript learning tutorial
Promise Regarding API, everyone should be able to use it proficiently, but You may still have knowledge blind spots related to microtasks.
Prerequisite knowledge
Before starting the text, let us first set the tone in advance for some of the content involved in this article.
Promise Which APIs involve microtasks?
In Promise, only callbacks that need to be executed after state changes are involved are considered microtasks, such as then
, catch
, finally
, all other code executions are macro tasks (synchronous execution).

In the above figure, blue indicates synchronous execution and yellow indicates asynchronous execution (thrown into the microtask queue).
When are these microtasks added to the microtask queue?
We look at this issue according to the ecma specification:
If the Promise status is pending at this time, then the successful or failed callbacks will be added to
[ [PromiseFulfillReactions]]
and[[PromiseRejectReactions]]
. If you have looked at the handwritten Promise code, you should be able to find that there are two arrays storing these callback functions.If the Promise status is non-pending at this time, the callback will become Promise Jobs, which are microtasks.
After understanding the above knowledge, the main film begins.
The same then, different micro-tasks are executed
Elementary
Promise.resolve() .then(() => { console.log("then1"); Promise.resolve().then(() => { console.log("then1-1"); }); }) .then(() => { console.log("then2"); });复制代码
Everyone should be able to get the correct answer from the above code: then1 → then1 -1 → then2
.
Although then
is executed synchronously, and the status has also changed. But this does not mean that every time we encounter then
, we need to throw its callback into the microtask queue. Instead, we wait for the callback of then
to complete and then execute the corresponding callback according to the situation. operate.
Based on this, we can draw the first conclusion: In the chain call, only after the previous then
callback is executed, the following Only the callbacks in then
will be added to the microtask queue.
Intermediate
Everyone knows that after Promise resolve
, the callback in then
will immediately enter the microtask queue.
So what do you think the output of the following code will be?
let p = Promise.resolve(); p.then(() => { console.log("then1"); Promise.resolve().then(() => { console.log("then1-1"); }); }).then(() => { console.log("then1-2"); }); p.then(() => { console.log("then2"); }); 复制代码
According to our initial understanding, it is not difficult to conclude that then2
will be output after then1-1
, but the actual situation is the opposite.
Based on this, we draw the second conclusion: The beginning of each chain call will first enter the microtask queue in sequence.
Next let’s change the way we write it:
let p = Promise.resolve().then(() => { console.log("then1"); Promise.resolve().then(() => { console.log("then1-1"); }); }).then(() => { console.log("then2"); }); p.then(() => { console.log("then3"); });复制代码
The above code actually has a trap, then
will return a new Promise every time, at this time p
is no longer generated by Promise.resolve()
, but by the last then
, so then3
should be in then2
is printed after.
By the way, we can also optimize the conclusion we reached before: The beginning of each chain call of the same Promise will first enter the microtask queue in sequence.
Advanced
Can you guess when then1-2
will be printed?
Promise.resolve() .then(() => { console.log("then1"); Promise.resolve() .then(() => { console.log("then1-1"); return 1; }) .then(() => { console.log("then1-2"); }); }) .then(() => { console.log("then2"); }) .then(() => { console.log("then3"); }) .then(() => { console.log("then4"); });复制代码
This question is definitely simple. Remember the first conclusion to get the answer. The following is the analysis:
First time
resolve
After the firstthen
callback enters the microtask queue and is executed, printthen1
the second time
resolve
After the first internalthen
callback enters the microtask queue, at this time all the external firstthen
callbacks have been executed, and the second externalneeds to be The then
callback is also inserted into the microtask queue.Execute the microtask, print
then1-1
andthen2
, and then add the callbacks inthen
respectively Insert the microtask queueto execute the microtask and print
then1-2
andthen3
. The following content will not be explained one by one
Next let’s modify return 1
, and the result will be quite different:
Promise.resolve() .then(() => { console.log("then1"); Promise.resolve() .then(() => { console.log("then1-1"); return Promise.resolve(); }) .then(() => { console.log("then1-2"); }); }) .then(() => { console.log("then2"); }) .then(() => { console.log("then3"); }) .then(() => { console.log("then4"); });复制代码
When we return Promise.resolve( )
, guess when then1-2
will be printed?
The answer is the last one printed.
Why is there such a big change in the execution order of microtasks for return
different things in then
? The following is the author's analysis.
PS:then
返回一个新的 Promise,并且会用这个 Promise 去 resolve
返回值,这个概念需要大家先了解一下。
根据 Promise A+ 规范
根据规范 2.3.2,如果 resolve
了一个 Promise,需要为其加上一个 then
并 resolve
。
if (x instanceof MyPromise) { if (x.currentState === PENDING) { } else { x.then(resolve, reject); } return; }复制代码
上述代码节选自手写 Promise 实现。
那么根据 A+ 规范来说,如果我们在 then
中返回了 Promise.resolve
的话会多入队一次微任务,但是这个结论还是与实际不符的,因此我们还需要寻找其他权威的文档。
根据 ECMA - 262 规范
根据规范 25.6.1.3.2,当 Promise resolve
了一个 Promise 时,会产生一个NewPromiseResolveThenableJob,这是属于 Promise Jobs 中的一种,也就是微任务。
This Job uses the supplied thenable and its then method to resolve the given promise. This process must take place as a Job to ensure that the evaluation of the then method occurs after evaluation of any surrounding code has completed.
并且该 Jobs 还会调用一次 then
函数来 resolve Promise
,这也就又生成了一次微任务。
这就是为什么会触发两次微任务的来源。
最后
文章到这里就完结了,大家有什么疑问都可以在评论区提出。
想了解更多编程学习,敬请关注php培训栏目!
The above is the detailed content of Promises that need to be truly understood. For more information, please follow other related articles on the PHP Chinese website!

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

JavaScript's applications in the real world include server-side programming, mobile application development and Internet of Things control: 1. Server-side programming is realized through Node.js, suitable for high concurrent request processing. 2. Mobile application development is carried out through ReactNative and supports cross-platform deployment. 3. Used for IoT device control through Johnny-Five library, suitable for hardware interaction.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft

SublimeText3 Linux new version
SublimeText3 Linux latest version

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

Dreamweaver CS6
Visual web development tools