The simplest way to see asynchronous code in action is with a timer.
setTimeout: do it later
setTimeout(callback, delay) runs a function once, after a delay in milliseconds (1000 milliseconds = 1 second):
console.log("1. Ordering pizza...");
setTimeout(() => {
console.log("2. ๐ Pizza has arrived!");
}, 2000);
console.log("3. Watching TV while we wait...");
It prints
1. Ordering pizza... 3. Watching TV while we wait... 2. ๐ Pizza has arrived!
Look at the order! JavaScript didn't stop and wait two seconds at the setTimeout. It scheduled the callback for later, immediately moved on to line 3, and then, two seconds later, came back and ran the callback.
This is the single most important thing to understand about asynchronous code: the code doesn't run in the order it's written. The callback runs later, after everything else has had its turn.
Here's an even more surprising example:
console.log("A");
setTimeout(() => console.log("B"), 0);
console.log("C");
It prints
A C B
Even with a delay of zero, "B" still comes last! A timer callback always waits until all the current code has finished running. (You'll find out exactly why at the end of this year, when we look at the event loop.)
To cancel a timer before it goes off, save the ID that setTimeout gives back, and pass it to clearTimeout:
const timerId = setTimeout(() => console.log("๐ฅ BOOM!"), 3000);
clearTimeout(timerId);
console.log("Phew. Bomb defused. ๐
");
It prints
Phew. Bomb defused. ๐
setInterval: do it again and again
setInterval(callback, delay) runs a function repeatedly, every delay milliseconds, until you stop it with clearInterval:
let count = 3;
const intervalId = setInterval(() => {
console.log(count);
count--;
if (count === 0) {
clearInterval(intervalId);
console.log("๐ Liftoff!");
}
}, 1000);
Output
3 2 1 ๐ Liftoff!
Each number appears one second after the last. Without clearInterval, it would keep going forever (or until you closed the page). Timers like this are used for clocks, countdowns, slideshows, and checking for new messages.