CoursePart 1 — JavaScript for PlaywrightLesson 1.15
Lesson 1.15Part 1 — JavaScript for Playwright

async / await

The most important concept for Playwright — waiting without the pain.

Lesson 1.15of 24
Next

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 complete
async-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.js

Step 3

Now you try

03

Copy the file above. Write a new async function called searchTest that:

  1. Calls navigateTo("/search")
  2. Calls fill("search box", "Playwright")
  3. Calls click("Search button")
  4. 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.js
Output
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.