0

Would some explain please, why await keyword causes the Hello World text to be placed in the middle (first example) and at the end (second example) of the output?

First example:

const getData = async() => { 
    var y = "Hello World"; 
    console.log(y); 
} 

console.log(1); 
getData(); 
console.log(2); 

Output of the first example:

1
Hello World
2

Second example:

const getData = async() => { 
    var y = await "Hello World"; 
    console.log(y); 
} 

console.log(1); 
getData(); 
console.log(2); 

Output of the second example:

1
2
Hello World
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Adam Ostrožlík
  • 1,256
  • 1
  • 10
  • 16
  • 3
    Because the second example will run async. – Keith Jan 23 '20 at 18:14
  • `await` will cause the rest of the code to be delayed until the expression after it resolves. It's automatic but it still shifts the rest to the microtask queue. [The beginning of my answer here addresses the behaviour](https://stackoverflow.com/a/59802836/3689450) – VLAZ Jan 23 '20 at 18:15
  • More of my answers that touch upon this in different contexts [concurrency](https://stackoverflow.com/a/58614717/) and [how `await` affects execution](https://stackoverflow.com/a/58292381/). Geez, basically any Promise answer I've done had to explicitly mention this behaviour... – VLAZ Jan 23 '20 at 18:30

1 Answers1

2

Both examples return a Promise, but there's a key difference that the scripting engine is looking for... Is there anything asynchronous being awaited therein? In the first example there isn't, but in the second example the code at least says there is. (Though I might expect any decent IDE to complain about it, since a string literal isn't an asynchronous operation. The language itself can be pretty forgiving about it though.)

Even if you do perform an asynchronous operation in the first example, unless you await it the surrounding code will still run synchronously. You just wouldn't have any way to observe the result (or failure) of that operation. (Well, you could append .then() to it, but then why use async? At that point you'd be mixing your asynchronous conventions.)

If you're calling getData() within an async function then you can await it:

console.log(1);
await getData();
console.log(2);

Or, alternatively, you can continue from the returned promise:

console.log(1);
getData().then(() => console.log(2));

Or, more verbosely (or for anybody stuck in IE):

console.log(1);
getData().then(function () {
    console.log(2);
});
David
  • 208,112
  • 36
  • 198
  • 279
  • Please, explain me why the first example does not return a promise even it is marked as async. Thx – Adam Ostrožlík Jan 23 '20 at 18:19
  • @AdamOstrožlík: Admittedly I hadn't noticed that in your example. This is mostly a guess, but I suspect it's because nothing therein uses `await` and the interpreter is smart enough to know that and execute the operations synchronously. The `await` keyword in the second example certainly isn't necessary, and any decent IDE should complain about it, but the language is probably taking it at its word and assuming the overall function needs to be a promise. – David Jan 23 '20 at 18:21
  • 1
    The first example *does* return a Promise. However, since there is no `await` inside the function, the entire code runs synchronously to completion. The return value is still a Promise but since it's never used, that's irrelevant. – VLAZ Jan 23 '20 at 18:23
  • @David: So do you think that if there was some fetch api call in the first example, the function would return a promise? – Adam Ostrožlík Jan 23 '20 at 18:24
  • @VLAZ: Under the hood is it just the presence of the `await` keyword which triggers the difference? I'm picturing other async/await constructs in other languages where if nothing is awaited then the whole thing is flattened out to a synchronous structure automatically by the compiler/interpreter. – David Jan 23 '20 at 18:25
  • 1
    @David yes, `await` is literally the only thing that shifts the execution to be done at a later point. Behind the scenes if you have `await ; ; ` it gets changed to something like `return new Promise((resolve) => {; resolve()})`. Well, if you use the `await`-ed value that will still be available but basically the rest of the code is just wrapped in a Promise. – VLAZ Jan 23 '20 at 18:28
  • I see it now in https://stackoverflow.com/questions/45594596/async-function-without-await-in-javascript Looks like await is something like setTimeout with only difference that it know when to end precisely Thanks for your help. – Adam Ostrožlík Jan 23 '20 at 18:29