Async JavaScript — Promises & Async/Await
Understand how JavaScript handles waiting — the key concept behind every Playwright test.
What you'll learn
- Understand why async code exists (waiting for things)
- Read and write async/await functions
- Handle errors with try/catch
- Understand why every Playwright action needs await
Playwright AutomationlessonsJump to another lesson
Async JavaScript --- Promises & Async/Await
This is the single most important concept for Playwright testing. Every Playwright command uses await. Nail this lesson and Playwright will make perfect sense.
Why Async Exists
Slow things that need waiting: loading webpages, calling APIs, reading files, clicking buttons in a browser test. If JavaScript froze each time, everything would lock up.
Order food
STAND HERE
Blocked!
Get food
Synchronous = blocking. You wait in line doing nothing.
Order food
Sit + do stuff
Food arrives
Asynchronous = not blocking. You can do other things while waiting.
Synchronous vs Asynchronous
Synchronous
- One line at a time, top to bottom
- Each line waits for the previous
- Simple, predictable order
Asynchronous
- Start a slow task, keep going
- Come back when it finishes
- Order may surprise you at first
// Async surprise:
console.log("1");
setTimeout(() => console.log("2"), 1000);
console.log("3");
// Output:
// 1
// 3 ← 3 runs before 2!
// 2 ← 2 arrives one second later
What is a Promise?
Three states: pending (still brewing), fulfilled (here’s your coffee!), rejected (we’re out of oat milk).
You rarely create Promises yourself. Functions like fetch() already return them. Your job is to handle them with await.
Async / Await
The await flow
call async function
returns Promise
a receipt
await pauses
value arrives
continue
How await pauses execution
- 1
Start the async function
async function getUser() { - 2
Hit await — function pauses here
const response = await fetch(url); - 3
Fetch finishes — resume with real value
// response is now actual data, not a Promise - 4
Another await — pause again
const user = await response.json(); - 5
All done — use the data
console.log(user.name); }
async function getUser() {
const response = await fetch("https://api.example.com/user");
const user = await response.json();
console.log(user.name);
}
Quick check
Where can you use the 'await' keyword?
Error Handling with try/catch
No error handling
- A failed fetch crashes your program
- No way to recover gracefully
- User sees a cryptic error
With try / catch
- Catches the error cleanly
- Show a friendly message, retry, etc.
- Program keeps running
async function fetchUser() {
try {
const response = await fetch("https://api.example.com/user");
const user = await response.json();
console.log("User:", user.name);
} catch (error) {
console.log("Oops, something failed:", error.message);
}
}
Why This Matters for Playwright
// Real Playwright test — notice async + await everywhere
test("user can log in", async ({ page }) => {
await page.goto("https://myapp.com/login");
await page.fill("#email", "alice@example.com");
await page.fill("#password", "secret123");
await page.click("#login-button");
await expect(page).toHaveURL("/dashboard");
});
Practice Exercises
Complete the Async Function
Add the missing async and await keywords to make this function work correctly.
function loadUserData() { const response = fetch("https://api.example.com/users"); const users = response.json(); console.log("Loaded", users.length, "users"); }
Fill in the Blank
To pause execution until a promise resolves, use the keyword.
Mini Challenge: try / catch
To handle errors from an await that might fail, wrap it in a try / block.