JavaScript handles asynchronous operations using several patterns that have evolved over time. Each pattern solves the same problem—non-blocking execution—but with different trade-offs.
A callback is a function passed as an argument and executed later.
function fetchData(callback) {setTimeout(() => {callback(null, "data");}, 1000);}fetchData((err, result) => {if (err) return;console.log(result);});
addEventListener)A Promise represents a value that will be available now, later, or never.
fetch("/api/data").then(res => res.json()).then(data => console.log(data)).catch(err => console.error(err));
Promise.all)async / awaitasync/await is syntactic sugar built on top of Promises, making async code look synchronous.
async function loadData() {try {const res = await fetch("/api/data");const data = await res.json();console.log(data);} catch (err) {console.error(err);}}
async/awaitasync/await for most code