I have two async functions in a module. Currently they are both just meant to wait, since the actual logic isn’t implemented yet.
Async module
export async function foo() {
return new Promise(resolve => {
setTimeout(() => {
console.log('foo');
}, 500);
});
}
export async function bar() {
return new Promise(resolve => {
setTimeout(() => {
console.log('bar');
}, 500);
});
}
In the main code, I am calling these two functions sequentially in another function. I want foo
to finishe before bar
starts, so I’m using await
.
Main code
import { foo, bar } from './myModule'
async function submit() {
await foo();
await bar();
// do other stuff
otherStuff();
}
submit();
This code logs ‘foo’ but then stops working. It doesn’t call bar
nor otherStuff
. What am I doing wrong?
Additionally, according to this answer, async functions always return a Promise. I tried removing the Promise from foo
and bar
, since both are declared as async, but then all functions are called without waiting for the previous one to finish, i.e. await
doesn’t have any effect at all.
>Solution :
When there are callbacks in your code – because of a library or the user of setTimeout()
for example – you may be forced to create promises by hand.
In this case, what you did is correct, but you forgot to resolve those promises! Said differently: you promised something, but you didn’t keep your word.
Here is the working code:
export async function foo() {
return new Promise(resolve => {
setTimeout(() => {
console.log('foo');
resolve();
}, 500);
});
}
export async function bar() {
return new Promise(resolve => {
setTimeout(() => {
console.log('bar');
resolve();
}, 500);
});
}
Additionally, according to this answer, async functions always return a
Promise
. I tried removing thePromise
from foo and bar, since both are declared as async, but then all functions are called without waiting for the previous one to finish, i.e. await doesn’t have any effect at all.
When the answer says "async functions always return a Promise
", it’s because declaring a function as async
will create a wrapper for you:
async function foo() {
return 1;
}
is a sugar syntax for:
function foo(): Promise<number> {
return Promise.resolve(1)
}
which works the same as:
function foo(): Promise<number> {
return new Promise(resolve => {
resolve(1)
})
}
But since you are currently using setTimeout()
, which uses a callback, this is not a promise. Something needs to be called back. So simply adding the sugar syntax async
will not do what you intend.
For example, imagine you attempt to do this:
async function foo() {
setTimeout(() => {
console.log('foo');
}, 500);
}
This will be equivalent to:
function foo(): Promise<ReturnType<typeof setTimeout>> {
return Promise.resolve(
setTimeout(() => {
console.log('foo');
}, 500);
)
}
Which is not what you want.