Introduction
Promises fixed the pyramid, but a long .then chain still reads like a machine. async and await are the same promises wearing readable clothes — no new power, just code that reads top to bottom, like normal code, like a story.
In this lesson you write the same job both ways, catch failures with try/catch, and learn the one teamwork trick — Promise.all — that stops independent jobs from wasting each other's time. (Roman Urdu: async/await wohi promise hai, bas parhne mein aam code jaisa seedha aur saaf lagta hai.)
Key points
asyncmakes a function return a promise — always — writeasync function load() { return "done"; }andload()gives a promise fulfilled with"done", even though you returned a plain value. A throw inside it becomes a rejection.awaitpauses inside the function only —const data = await getData();waits right there until the promise settles, then continues with the real value — no.thencallback needed.(Roman Urdu: await sirf usi function ko rokta hai — baaki program aur page bilkul nahi rukte.)- The rest of the program does NOT freeze — while an
asyncfunction waits at anawait, other code outside it keeps running, timers keep ticking, the page stays alive. Only that one function is paused. - The same job reads like a story — a
.thenchain nests the steps in callbacks;async/awaitwrites them as plain lines in order: get the user, get the orders, print the result. Same promises underneath. - Failures go in
try/catch— wrap yourawaitlines intry { ... } catch (error) { ... }. When the awaited promise rejects, it throws into thecatchblock, exactly like a normal error. awaitone-by-one adds the times up — three independent jobs of 1 second each, awaited in a row, take 3 seconds. They never needed to wait for each other.Promise.allruns them together —await Promise.all([jobA(), jobB(), jobC()])starts all three at once and finishes in the time of the longest single job — 1 second in that example, not 3. It fulfills with an array of all values, in order; if any one rejects, the wholePromise.allrejects.(Roman Urdu: Alag alag await matlab saara waqt jama — Promise.all sab ko saath chalata hai, waqt sirf sab se lambe kaam ka lagta hai.)awaitlives insideasyncfunctions — usingawaitin a plain function is a syntax error. (One honest exception: at the top level of a JavaScript module file,awaitis allowed.)
Code examples
Example 1 — The same job with a .then chain
function getMessage() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Hello from the server");
}, 1000);
});
}
getMessage()
.then((message) => {
console.log("Message received: " + message);
})
.catch((error) => {
console.log("Failed: " + error.message);
});
console.log("Request sent, waiting...");What it does: getMessage pretends to be a slow server job: it returns a promise that fulfills after 1 second with a message. The .then callback receives the message when it arrives; .catch stands guard below it. This is the promise style from Lesson 3.20, working perfectly.
What you will see: at once: Request sent, waiting.... After 1 second: Message received: Hello from the server. Correct — but the real work hides inside a callback, and with four or five steps the chain grows hard to follow.
Example 2 — The same job with async/await, plus try/catch
function getMessage() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("Hello from the server");
}, 1000);
});
}
function getBrokenMessage() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("Server is down"));
}, 1000);
});
}
async function showMessages() {
try {
const message = await getMessage();
console.log("Message received: " + message);
const broken = await getBrokenMessage();
console.log("This line never runs: " + broken);
} catch (error) {
console.log("Failed: " + error.message);
}
console.log("Function finished");
}
showMessages();
console.log("Request sent, waiting...");What it does: The exact same first job, written with await inside an async function. The code reads in order, like a story: wait for the message, print it. Then a second job that rejects after 1 second — the await throws into catch, the line after it is skipped, and the function still finishes cleanly.
What you will see: at once: Request sent, waiting... — proof the program did not freeze at the await. After 1 second: Message received: Hello from the server. After 1 more second (2 seconds from the start): Failed: Server is down then Function finished. The line This line never runs never appears.
Example 3 — One-by-one vs Promise.all: the timing lesson
function job(name) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(name + " done");
}, 1000);
});
}
async function runOneByOne() {
console.log("One by one: start");
const a = await job("A");
console.log(a);
const b = await job("B");
console.log(b);
const c = await job("C");
console.log(c);
console.log("One by one: finished");
}
async function runTogether() {
console.log("Together: start");
const results = await Promise.all([job("A"), job("B"), job("C")]);
console.log(results[0]);
console.log(results[1]);
console.log(results[2]);
console.log("Together: finished");
}
async function main() {
await runOneByOne();
await runTogether();
}
main();What it does: Three independent jobs, each taking 1 second. runOneByOne awaits them in a row, so each waits for the last — the times add up. runTogether starts all three at the same moment with Promise.all, so the wait is only as long as the slowest single job.
What you will see: at once: One by one: start. Then A done after 1 second, B done after 2 seconds, C done after 3 seconds, then One by one: finished — 3 seconds total. Next, Together: start, and just 1 second later (4 seconds from the very beginning) all three lines arrive together: A done, B done, C done, then Together: finished. Same three jobs: 3 seconds in a queue, 1 second as a team.
Quick recap
asyncmakes a function always return a promise;awaitpauses only inside that function until the promise settles — the program never freezes.- Wrap
awaitlines intry/catch: a rejection throws intocatch, like a normal error. - Independent jobs awaited in a row take the sum of their times;
Promise.allstarts them together and takes only the longest single time.
Common mistakes
- Forgetting
await—const data = getData();withoutawaitstores the promise object, not the value, and printing it showsPromise { <pending> }. The fix:const data = await getData();inside anasyncfunction. - Using
awaitin a plain function — the file stops with a syntax error before anything runs. The fix: mark the functionasync—awaitonly lives insideasyncfunctions (or at the top level of a module). - Awaiting independent jobs one by one — three 1-second jobs that do not depend on each other take 3 slow seconds in a row. The fix: start them together with
await Promise.all([jobA(), jobB(), jobC()])and pay only the longest single time.
Practice
- Write an
async function greet()that awaits a promise which resolves with your name after 1 second, then logsWelcome,plus the name. Add aconsole.logafter thegreet()call and confirm it prints before the welcome line. - Make three jobs that each resolve after 1 second with the numbers 10, 20 and 30. First add their results with three separate
awaitlines and time it (about 3 seconds). Then rewrite it withPromise.alland confirm the same total — 60 — arrives in about 1 second.