Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
338 views
in Technique[技术] by (71.8m points)

javascript - Why does this async function execute before the equivalent Promise.then chain defined before it?

I have the following code:

var incr = num => new Promise(resolve => {
  resolve(num + 1);
});

var x = incr(3)
  .then(resp => incr(resp))
  .then(resp => console.log(resp));

async function incrTwice(num) {
  const first = await incr(num);
  const twice = await incr(first);
  console.log(twice);
}

incrTwice(6);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First of all, let me point out that you never should argue about the execution order of independent promise chains. There are two asynchronous calls, and they do not depend on each other but run concurrently, so they should always be expected to finish in arbitrary order.

Toy examples that only use immediately-resolving promises make this order depend on microtask queueing semantics instead of actual asynchronous tasks, which makes this a purely academic exercise (whose result is subject to changes in the spec).

Anyway, let's clear up your misunderstandings:

the stack is empty between the declaration of x and incrTwice which would cause the microtask queue to be flushed

No, the stack only becomes empty after all user code is ran to completion. There's still the global execution context of the <script> element on the stack. No microtasks are executed until all synchronous code (incr = …, x = incr(3).… and incrTwice(6)) has finished.

I believe [the code] shows two equivalent ways to achieve the same functionality: first by chaining promises and second with the syntactic sugar of async/await.

Not exactly. The .then() chaining has an additional resolve step when unnesting the incr(resp) promise that is returned from the first .then(…) handler. To make it behave precisely the same as the awaited promises in incrTwice, you'd need to write

incr(3).then(resp =>
  incr(resp).then(resp =>
    console.log(resp)
  )
);

If you do that, you'll actually get the console logs in the order in which you started the two promise chains because they will take the same number of microtasks until the console.log() is executed.

For more details, see What is the order of execution in javascript promises, Resolve order of Promises within Promises, What happen when we return a value and when we return a Promise.resolve from a then() chain, in the microtask queue?, What is the difference between returned Promise?, ES6 promise execution order for returned values


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...