Reputation: 1
My case:
let waiting = function () {
return new Promise(resolve => {
console.log('awaiting...');
setTimeout(function () {
resolve();
}, 1000)
});
};
let waitingAsync = async function () {
console.log('start...');
await waiting();
console.log('stop...');
};
waitingAsync();
console.log('done...');
There are 2 things I don't understand in the code:
The first:
await waiting();
waiting
is a synchronous function (because it doesn't have async
keyword). So, why can I await a synchronous function?
The second:
Why couldn't done...
message be awaited after completing waitingAsync
function?
And main question: waitingAsync
is an asynchronous function, why is await
keyword not required when calling it? Just waitingAsync()
instead of await waitingAsync()
.
If I can await waitingAsync()
, done...
message would be printed last.
Upvotes: 4
Views: 8135
Reputation: 5767
Before diving in, it's good to notice a few things.
Any reader of the code snippet
let waiting = function () {
return new Promise(resolve => {
console.log('awaiting...');
setTimeout(function () { resolve(); }, 1000);
});
};
let waitingAsync = async function () {
console.log('start...');
await waiting();
console.log('stop...');
};
waitingAsync();
console.log('done...');
may be mislead to believe that the output will be
start...
awaiting...
stop...
done...
while – as you have already noted – done...
gets printed before
stop...
.
The reason is that waitingAsync();
is a call to an asynchronous function,
while console.log('done...');
is just a normal sequential/synchronous
statement that gets carried out right away.
Question 1:
waiting
is a synchronous function (because it doesn't haveasync
keyword) [?]
Answer:
False. The function waiting
is asynchronous – it returns
a Promise.
Question 2:
Why couldn't
done...
message be awaited after completingwaitingAsync
function?
Answer:
Because console.log('done...')
is not asynchronous.
(It does not return a Promise.)
Question 3:
And main question:
waitingAsync
is an asynchronous function, why isawait
keyword not required when calling it?
Answer:
Well, in your example waitingAsync
does not return any value. -
If it would return a value that you care about, then you would need to await
it to get it.
(Hello world!
in my Stack Snippet below.)
Question 4:
If I can await
waitingAsync()
, [the]done...
message would be printed last [?]
Answer:
That depends on what exactly you mean. – See my Stack Snippet below!
As long as the Done!
message is printed within the same callback as the call
await waitingAsync()
, the answer is Yes!
But if you put console.log('done...?')
after the call to the asynchronous
function that encloses await waitingAsync()
then the answer is No!
When running the snippet below, pay attention to the order of the output!
Also notice how it takes 1400 ms for Promise resolved!
to show up.
function waiting () {
return new Promise(resolve => {
console.log('awaiting...');
setTimeout(function () {
resolve('Hello world!');
console.log('Promise resolved!');
}, 1400);
});
}
async function waitingAsync () {
console.log('start...');
const toBeReturned = await waiting();
console.log('stop...');
return toBeReturned;
}
(async () => {
console.log('Heads up! The next line makes an asynchronous call.');
console.log('Result: ' + await waitingAsync()); // 'Hello world!'
console.log('Done! This will be printed LAST! - Agreed?');
})();
console.log('done...?? This is LAST in the CODE. - I awaited \
"waitingAsync()" above. - So will this be printed at the very end??');
.as-console-wrapper { max-height: 100% !important; top: 0; }
The last asynchronous function is anonymous – without name – and gets
called immediately.
In fact, this is the only function that gets called directly in the snippet.
The function waitingAsync
is only called indirectly (by the anonymous
function), and the function waiting
is also called indirectly
(by waitingAsync
).
Don't ever put sequential/synchronous code after and outside a call to an asynchronous function!
You will just confuse yourself if you do. – And even if you don't get confused, other readers of your code almost certainly will be.
Upvotes: 1
Reputation: 6788
When you await
a function, if that function returns a promise, its return value will be treated as the promise then
value. If the promise will reject, it will be cast to an Error. If the function call returns something ohter than a thenable, well, await
then just doesn't nothing.
In the other hand, when you declare an async
function, its return value will be returned as a Promise, and any Error thrown from it will be casted to a rejected Promise.
You can use await
only within an async
declared function.
that's just about async
and await
are, just automatic casting to promises. You don't actually need code using await and async to be really asynchronous (while, well, it's not really useful).
A quick demonstration:
//Will return the string 'Promise' if called through `await`
function getPromise(){
return Promise.resolve('Promise');
}
//Casted to Promise.reject thrught await
function throwError(){
return Promise.reject('error');
}
function get(){
return 'something simple';
}
async function getAsync() {
var response = await getPromise();
return response;
}
//await will cast the rejected Promise to an error
async function getErrorAsync() {
var response = await throwError();
return response;
}
async function simpleGet(){
return get();
}
async function redundantGet(){
return await get();
}
async function catchTheError(){
try{
await throwError();
}
catch(e){
console.log('an error: ' + e );
}
return 'whatever';
}
getAsync().then( console.log ); //Promise
getErrorAsync().catch( console.log ); //error
simpleGet().then( console.log ); //something simple
redundantGet().then( console.log ); //something simple
catchTheError(); //will log 'an error: error'.
So:
waiting is a synchronous function (because it doesn't have async keyword). So, why can I await a synchronous function?
Because you can. The only thing await
does is to resolve promise to real values and errors. You don't actually need the function to return a promise.
Why couldn't done... message be awaited after completing waitingAsync function?
async
and await
only makes your code to behave as it would be synchronous iside async
declared functions. Your last console.log('done')
is outside any async
function, so it will be just logged before that function ends, since it is asynchronous.
And main question: waitingAsync is an asynchronous function, why is await keyword not required when calling it? Just waitingAsync() instead of await waitingAsync().
Because async
keyword casts values to promises -and allows to use await
- and nothing more. In fact, since you can only use await
inside async
functions... you can't expect async
functions to be called through await
, you would need infinite async
functions :-D.
Upvotes: 1
Reputation: 56
A async
function does return a promise or, when it uses the await
keyword, it must wait for a asynchronous function, being a Promise or another async
function. In your code, waiting()
is a function that returns a Promise. Then, await waiting()
is correct (since it is waiting for a asynchronous function).
An async
function is called as another basic functions is called. You may mark a function as async when you desire operate it as an asynchronous function and using the 'await' keyword. The 'done...' is printed because when you call asyncFunction()
, it must await
until waiting promise
is finished. But the program is not stopped and go on showing done...
. If you want to wait for it, maybe you can use asyncFunction().then( () => console.log('done...') )
Upvotes: 2
Reputation: 222369
This isn't a function but a value that it returns which is awaited with await
statement.
async
and normal functions aren't different to the caller. async
just returns a promise without returning it explicitly when being called. The result of waitingAsync()
call is a promise. The result of waiting()
call is a promise, too, so it isn't 'synchronous'.
According to the spec, both promises and non-promises can be await
ed. Non-promises are converted to promises with Promise.resolve()
.
console.log('done...')
can't be awaited because it isn't called inside async
function. And it doesn't have to be await
ed because it doesn't return a promise but undefined
. await
ing it would be possible within async
function. These await
usages are equal and equally useless, all they do is 1 tick delay:
async function ... {
...
await console.log('done...');
}
async function ... {
...
console.log('done...');
await undefined;
}
async function ... {
...
await Promise.resolve(console.log('done...'));
}
Upvotes: 5
Reputation: 1037
Async
keyword used to specify that function will be an instance of AsyncFunction
so it will return Promise
.
Await
is used to wait for a promise resolving inside of async function.
According to a mdn - async function can contain an await
expression, that pauses the execution of the async function and waits for the passed promise's resolution, and then resumes the async function's execution and returns the resolved value.
Upvotes: 2