4

This is my code, I don't know what happened when I using the async keyword, if remove the async keyword, the result of print is different

async function async2() {
  return new Promise((resolve) => resolve('hello'))

}
async2().then((res) => {
  console.log(res)
  console.log('async1')
})

Promise.resolve()
  .then(() => {
    console.log(1)
  })
  .then(() => {
    console.log(2)
  })
  .then(() => {
    console.log(3)
  })

it will print

1
2
hello
async1
3

If remove the async keyword of async2 function, it will print

hello
async1
1
2
3

function async2() {
  return new Promise((resolve) => resolve('hello'))

}
async2().then((res) => {
  console.log(res)
  console.log('async1')
})

Promise.resolve()
  .then(() => {
    console.log(1)
  })
  .then(() => {
    console.log(2)
  })
  .then(() => {
    console.log(3)
  })

What will happen if an async function intentionally returns a promise?

I want to know what happened when I add the async keyword.

Barmar
  • 741,623
  • 53
  • 500
  • 612
Tom
  • 43
  • 4
  • Does this answer your question? [async/await implicitly returns promise?](https://stackoverflow.com/questions/35302431/async-await-implicitly-returns-promise) – Wyck Jun 30 '23 at 16:19
  • 2
    @Wyck No. Rather https://stackoverflow.com/questions/62405525/why-does-this-async-function-execute-before-the-equivalent-promise-then-chain and similar ones, though I think we don't have an exact duplicate for this particular case. – Bergi Jun 30 '23 at 16:24
  • Both run look the same to me – slebetman Jun 30 '23 at 16:36
  • [This](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function#:~:text=Even%20though%20the%20return%20value%20of%20an%20async%20function%20behaves%20as%20if%20it%27s%20wrapped%20in%20a%20Promise.resolve%2C%20they%20are%20not%20equivalent.) is related, but doesn't actually answer your question – Zachiah Jun 30 '23 at 16:59
  • @slebetman What browser are you using? – InSync Jun 30 '23 at 17:05
  • 1
    @slebetman I get the described result when I run the snippets. I'm using the latest Google Chrome. – Barmar Jun 30 '23 at 17:05
  • I think this has something to do with the way that the nested promise is added to the microtask queue. When you resolve a promise, if it returns another promise it will be resolved automatically. – Barmar Jun 30 '23 at 17:06
  • Yes both results you describe look the same to me. "hello" and "async1" happen together since they're synchronous. It is bad practice to predict the order of the other things. If you do go down the path to try to understand the order it will make you a bad programmer. Asynchronous means not being able to predict the order and you should have the mental state of not trying to predict the order. If you need your code to execute in a specific order then write code to happen in specific order - not try to guess the order. – slebetman Jun 30 '23 at 19:17

1 Answers1

3

The difference is that an async function already returns a promise implicitly, and that promise is later resolved with the result value when the return statement is encountered:

async function() {
  …;
  return new Promise(…);
}

is (in the simple case with no await in the ) equivalent to

function() {
  return new Promise(resolve => {
    …;
    resolve(new Promise(…));
  })
}

However, resolving that implicit promise with your explicit new Promise(…) takes an extra tick or two in the promise job queue, which you can observe when starting the separate promise chain at the same time and all of the promises are immediately resolved, not actually doing any asynchronous work.

In real code, the difference does not matter, and you should never need to care about such details, just like with other subtle execution order differences.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 2
    IMHO trying to understand this is bad practice. Write proper asynchronous code and always assume that asynchronous events can happen in random order - if you need to handle things in a specific order you should write a proper promise chain (or use awaits) not try to figure out how the event loop handle events. – slebetman Jun 30 '23 at 19:19
  • @slebetman I could not agree more. That's why I didn't try to give a detailed explanation about what happens in what tick or how many ticks exactly there are - also such details are prone to change due to better optimisations. – Bergi Jun 30 '23 at 22:11
  • The "subtle execution order differences" explains why @slebetman got the same results from both versions in their browser. – Barmar Jun 30 '23 at 22:40
  • @Barmar You misunderstand me. I'm saying `1,2,hello,async1,3` is **exactly the same as** `hello, async1, 1, 2, 3` which again is **exactly the same** as (meaning zero difference) `1, 2, 3, hello, async1`. That is: `hello, async1` happens together. `1` happens on its own. `2` happen on its own and `3` happen on its own as well as `2` happening after `1` and `3` happening after `2`. That is all that's happening – slebetman Jul 01 '23 at 06:55