Lesson 1.15Part 1 — JavaScript for Playwright
async / await
The most important concept for Playwright — waiting without the pain.
Step 1
The idea
01
Promises work — but chaining .then().then().catch() gets messy fast. async/await is cleaner syntax for the exact same thing.
Two keywords, one rule:
- async— put this in front of a function to mark it as "this function contains asynchronous code"
- await— put this in front of a Promise to say "wait here until this Promise resolves"
You can only use await inside an async function. That's the only rule.
Step 2
See it run
02
Output
Running login test...
Navigated to login page
Filled username
Filled password
Clicked Login button
Logged in as: priya@example.com
Test completeasync-await.js
// Simulated Playwright-style actions
function navigateTo(url) {
return new Promise(resolve =>
setTimeout(() => { console.log(`Navigated to ${url}`); resolve(); }, 200)
);
}
function fill(field, value) {
return new Promise(resolve =>
setTimeout(() => { console.log(`Filled ${field}`); resolve(value); }, 100)
);
}
function click(button) {
return new Promise(resolve =>
setTimeout(() => { console.log(`Clicked ${button}`); resolve(); }, 100)
);
}
// Without async/await (messy .then chains)
// navigateTo("/login").then(() => fill("username", "...")).then(() => click("Login")).then(...)
// WITH async/await — reads top to bottom, like synchronous code
async function loginTest() {
console.log("Running login test...");
await navigateTo("/login");
const user = await fill("username", "priya@example.com");
await fill("password", "secret");
await click("Login button");
console.log(`Logged in as: ${user}`);
console.log("Test complete");
}
// Call the async function
loginTest();Terminal
$ node async-await.jsStep 3
Now you try
03
Copy the file above. Write a new async function called searchTest that:
- Calls
navigateTo("/search") - Calls
fill("search box", "Playwright") - Calls
click("Search button") - Prints "Search test complete"
Call searchTest() at the bottom. Make sure all steps use await.
⚠️Warning
Forgetting
await is the #1 beginner Playwright bug. If you skip it, the next line runs before the action finishes. Always await every Playwright method call.Step 4
Why a tester cares
04
Here's the same user-loading example from Lesson 1.14, rewritten with async/await. Compare how much cleaner it reads:
load-user-async.js
function fetchUser(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (id > 0) resolve({ id, name: "Priya", email: "priya@example.com" });
else reject(new Error("User ID must be positive"));
}, 300);
});
}
// With .then() — works but hard to read when chained
// fetchUser(42).then(u => loadProfile(u)).then(p => render(p))...
// With async/await — reads top to bottom, like normal code
async function showUserProfile(id) {
const user = await fetchUser(id);
console.log(`User: ${user.name}`);
console.log(`Email: ${user.email}`);
console.log("Profile loaded successfully.");
}
showUserProfile(42);Terminal
$ node load-user-async.jsOutput
User: Priya
Email: priya@example.com
Profile loaded successfully.Same Promise underneath — but now it reads like a plain list of steps. async/await doesn't change how JavaScript handles timing; it just makes the code readable.
Recap
3 key points
- 1async marks a function as asynchronous — it always returns a Promise implicitly.
- 2await pauses execution inside an async function until the Promise resolves.
- 3You can only use await inside an async function — it's a syntax error otherwise.
Up next
Lesson 1.16 — try / catch