Another way to think about this is consider how this code would work if you just used callbacks
rather than async/await and or Promises.
At the end of the day async/await is “syntax sugar” on Promises and Promises themselves are “syntax sugar” around callbacks that all focus around the concept of JS “combing back to a call” or a “call-back”.
So going back to the code, this snippet:
async function rainbow() {
delayedColorChange('red', 1000)
}
console.log(rainbow());
would work the same as:
function rainbow() {
delayedColorChange('red', 1000)
return Promise.resolve();
}
console.log(rainbow());
this also is the same:
function rainbow() {
return Promise.resolve();
}
console.log(rainbow());
Now at this point, you might be asking “but wait, what about my delayedColorChange
when is it executed?” It is executed as you called it, but that doesn’t mean your code cares about what it returns/does after its called. Your code just keeps marching along, and doesn’t care about “getting called back” from what is returned from delayedColorChange
If you noticed, there are functions within delayedColorChange
that are called “later”, IE the one function you passed into setTimeout
will be “called back”, so the color is changed at the right time.
The idea that JavaScript can be “called back” all over the place, out of order is one of the reasons why its fast, even though it can only be in 1 place at 1 time.
So just to finalize, if you do care about when delayedColorChange
is “finished” here’s the three ways to do it:
callback
const delayedColorChange = (newColor, delay, doneFn) => {
setTimeout(() => {
document.body.style.backgroundColor = newColor
doneFn();
}, delay)
})
}
async function rainbow() {
delayedColorChange('red', 1000, () => console.log('DONE!'))
}
Promise based (this is similar to your except we will remove async/await for simplicity
const delayedColorChange = (newColor, delay) => {
return new Promise((resolve) =>
setTimeout(() => {
document.body.style.backgroundColor = newColor;
resolve();
}, delay)
);
};
function rainbow() {
delayedColorChange("red", 1000).then(() => console.log("DONE!"));
}
async/await based
const delayedColorChange = (newColor, delay) => {
// **note** you still need a Promise to "wrap" the callback of setTimeout
return new Promise((resolve) =>
setTimeout(() => {
document.body.style.backgroundColor = newColor;
resolve();
}, delay)
);
};
async function rainbow() {
await delayedColorChange("red", 1000);
console.log("DONE!");
}
note the original snippet posted essentially says “do delayedColorChange()” then immediately leaves the function not caring about the result. This doesn’t mean delayedColorChange
doesn’t happen/is fired, its just you don’t care about what it resolves to.