Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to achieve faster await with V8

2025-01-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article introduces the knowledge of "how to achieve faster await in V8". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Example

First, take a look at the code:

Const p = Promise.resolve ()

(async () = > {

Await p

Console.log ("after:await")

) ()

P.then () = > {

Console.log ("tick:a")

}) .then (() = > {

Console.log ("tick:b")

});

Based on the implementation result of node v10, the implementation of node v8 does not conform to the ECMAScript standard.

Good programmers can always explain complex principles with simple examples. The code is simple, but the execution results may come as a surprise to many people:

Tick:a

Tick:b

After:await

If you have guessed right, you have mastered the key content of this article, so you don't have to read on:).

Why does after:await appear after tick:a, even after tick:b? To understand the principle, we can do a small experiment.

Translate await into promise

The V8 blog explains the execution logic of await in pseudo-code:

Original https://v8.dev/_img/fast-async/await-under-the-hood.svg

We can use promise syntax to write:

Function foo2 (v) {

Const implicit_promise = new Promise (resolve = > {

Const promise = new Promise (res = > res (v))

Promise.then (w = > resolve (w))

});

Return implicit_promise

}

In the same way, the code at the beginning of the article can be converted to:

Const p = Promise.resolve ()

(() = > {

Const implicit_promise = new Promise (resolve = > {

Const promise = new Promise (res = > res (p))

Promise.then () = > {

Console.log ("after:await")

Resolve ()

});

});

Return implicit_promise

) ()

P.then () = > {

Console.log ("tick:a")

}) .then (() = > {

Console.log ("tick:b")

});

After some trivial debugging, it is found that the real key code of the problem is this sentence: const promise = new Promise (res = > res (p))

Resolved with another promise

Children's shoes who are familiar with Node.js or browser event loops know that the callback function (reaction) of resolved promise is placed in a separate queue MicroTask Queue. This queue is executed at the end of the event loop, and only when the queue is cleared can you move on to the next phase of the event loop.

We know that the return value of a promise .then callback can be an arbitrary value or another promise. But the processing logic of the latter may be a bit counterintuitive.

Before going any further, let's briefly talk about several states of promise:

When we say that a promise is resolved, it means that it cannot be fulfill or reject again, either by fulfill or by reject (in both cases, promise has a definite non-promise result), or to follow another promise (along with fulfill or reject)

When we say that a promise is unresolved, it means that it has not been resolve.

When a promise (let's say promiseA. When easily referenced by resolve and following another promise (called p), the execution logic is very different from the previous two resolve cases, expressed in pseudocode:

AddToMicroTaskQueue (() = > {/ / Task A

/ / use the .then method to bind the state of promiseA to p

P.then (

ResolvePromiseA, / / Task B

RejectPromiseA

);

});

Let's analyze it step by step:

First, we add task A to MicroTask Queue, which is defined as PromiseResolveThenableJob in the ECMAScript standard

The main purpose of task An is to make promiseA follow the state of p and associate the states of the two.

Since p in our example is already resolved (state is fulfilled), add resolvePromiseA task B to MicroTask Queue immediately

PromiseA is the resolved after the resolvePromiseA is executed (fulfilled value with a status of fulfilled and a value of p)

We can see that from new Promise (res= > res (p)) to the promise returned by this call, microtick-- is actually required by resolve at least twice. In our case, MicroTask Queue is traversed twice.

At this point, we can finally figure out the order in which the opening code is executed:

Updated on January 28, the order of the tasks in the micro-task queue was not considered before. Make some modifications here. The tasks in the following queue are related to the order, from left to right, and the tasks on the left are executed first.

1. After the code has been executed

MicroTask Queue has two tasks: PromiseResolveThenableJob,tick:a

2. Start executing runMicrotasks ()

MicroTask Queue becomes: resolvePromiseA,tick:b

Console: tick:a

3. The MicroTask Queue is not empty and continues to execute the tasks in the queue

MicroTask Queue becomes: after:await

Console: tick:a, tick:b

4. Continue to execute and clear the MicroTaak Queue

Console: tick:a, tick:b, after:await

This is the end of "how to achieve faster await in V8". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report