Should javascript async function be called with await keyword?
That depends. If you want the logic where the code is calling foo()
to wait until foo
has completed its asynchronous work, then yes, you should use await
.
If you don't want the logic at the call site to wait for foo
to finish its work, don't use await
, but do store the promise it provides and await
(or otherwise use it) at some point. Otherwise, you won't handle it if the promise is rejected, and not handling promise rejections is a source of bugs.
So either (in an async
function):
await foo();
or (in a non-async
function):
return foo(); // Let the caller handle the promise
or (in a non-async
function where you can't return the promise to your caller):
foo()
.then(value => {
// ...use value (except your `foo` doesn't return one,
// so really this is just "foo worked")...
})
.catch(error => {
// ...handle/report error...
});
etc.
Fundamentally, though: An async
function returns a promise, so you should do something to handle that promise (by passing it back to your caller, or handling it locally, etc.).
Let's look at what happens in an async
function calling foo
when call
fails, both with and without await
:
With await
:
async function call(test) {
if (test === undefined) {
throw new Error("'test' is required");
}
// Stand-in for something asynchrojous using `test`
const result = await new Promise(resolve => {
setTimeout(() => {
resolve(test * 2);
}, 10);
});
return result;
}
async function foo(test) {
const value = await call(test)
console.log(`foo got value: ${value}`);
}
async function example() {
foo();
}
example()
.then(() => {
console.log("All done, no errors");
})
.catch((error) => {
console.error("Error: " + error);
});
When you run that, it says "All done, no errors" but if you look in the devtools console, you'll see "Uncaught (in promise) Error: 'test' is required" (an unhandled rejection).
Compare with using await
:
async function call(test) {
if (test === undefined) {
throw new Error("'test' is required");
}
// Stand-in for something asynchrojous using `test`
const result = await new Promise(resolve => {
setTimeout(() => {
resolve(test * 2);
}, 10);
});
return result;
}
async function foo(test) {
const value = await call(test)
console.log(`foo got value: ${value}`);
}
async function example() {
await foo();
}
example()
.then(() => {
console.log("All done, no errors");
})
.catch((error) => {
console.error(error);
});
As you can see, the error from call
was caught (it propagated from call
to foo
, then from foo
to example
, then from example
to where we call it and handle errors).