Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ECMAScript7 async/await inconsistent behavior depending on whether using brackets in arrow function or not

I am experiencing inconsistent behavior in Google Chrome 60.0.3112.78 (Official Build) (64-bit) when using modern ES6+ async/await, depending on whether I use brackets in the arrow function that returns a Promise. The same happens in Node.js. I am having trouble understanding why.

I understand that this is not how to implement a sleep() function but it is the easiest way to demonstrate. Consider the following example code snippet.

function sleep(ms = 0) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

(async () => {
  console.log('a');
  await sleep(5000);
  console.log('b');
})()

As expected, this will write a to the console, wait 5 seconds and then write b to the console.


Shorter notation using an arrow function to return the Promise.

const sleep = ms => { return new Promise(resolve => setTimeout(resolve, ms)) }

(async () => {
  console.log('a');
  await sleep(5000);
  console.log('b');
})()

As expected this code behaves the same. a and b are written to the console with a 5000 millisecond interval in between.


The following code does not work. The only difference is that I am not wrapping the return of the Promise in brackets on the first line.

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))

(async () => {
  console.log('a');
  await sleep(5000);
  console.log('b');
})()

In this case, await sleep does not work. In fact, this code does absolutely nothing at all. It does not log anything to the console, not a and not b.

I consider myself fairly experienced but I don't currently understand this. Why do the brackets matter in this particular case? The return value is identical, right? And how come not even the character a is console logged?

Somebody please explain to me exactly and specifically why this is the way it is. Is this a bug or do I just need sleep myself?

Thank you very much.

like image 732
Jochem Stoel Avatar asked Aug 18 '26 22:08

Jochem Stoel


1 Answers

It's the semicolon after the arrow function that matters. Write

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
//                                                                 ^

and it will work. Notice that the next line starts with (, which is a syntactically valid continuation, so ASI doesn't jump in. Your code is parsed and interpreted as

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))(async () => { … })()

but the function sleep is never called.

like image 195
Bergi Avatar answered Aug 20 '26 13:08

Bergi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!