# Up Next: Working Like a Professional

See what your code can wait for after Module 5, meet the Trivia Night project where you'll build a timed game with live questions, and get a first look at Module 6, starting with a test that catches a bug before a player does.

Journeyman · JavaScript · Web Development · Updated October 31, 2026

## After this lesson you can

- Choose the Module 5 tool that fits an asynchronous job, from setTimeout and promises to fetch and response.ok

## Key takeaways

- After Module 5 you can schedule work with timers, wait for promises with async and await, load live data with fetch, and handle every way a request can fail.
- Trivia Night hands you a page. You fetch real questions, run a 15-second countdown, keep score, and cope when the trivia API is down.
- Each waiting job has a tool. Timers wait for time, promises and await wait for work, fetch asks an API, and response.ok and try/catch handle failure.
- Module 6 is how professionals work, with packages, a dev server, tidy code, tests that catch bugs before users do, and an app online at a link you can share.

At the start of this module, every line of your code ran the moment it was reached, and a page that had to wait would have frozen. Now your code waits without blocking anything: for a timer, for a promise, for an answer from a server on the other side of the world. And when that answer is slow, empty or never comes, your page says so in words a person understands. That's the difference between a page and an app.

This lesson looks back at what you can do, shows you the project where you'll put it all together, and gives you a first look at Module 6, where you start working the way professional developers do.

## What you can do now

After Module 5, you can:

- **explain why code can't stand and wait**, and how the event loop lets one thread keep a page working;
- **schedule work** with `setTimeout` and `setInterval`, and cancel it with `clearTimeout` and `clearInterval`;
- **wait for work that takes time** with promises, `then`, `catch` and `finally`, or more clearly with `async` and `await`;
- **wait for several things at once** with `Promise.all`, `Promise.allSettled`, `Promise.race` and `Promise.any`;
- **read an API's address**, its method, its status code and its JSON;
- **load live data** with `fetch` and `response.json()`, and **send data** with a `POST`;
- **catch every failure**: a bad status with `response.ok`, no answer with `try`/`catch`, a slow server with `AbortSignal.timeout`;
- **show loading, empty and error states**, with a **Try again** button.

Here's a lot of that in a dozen lines: three dog photos for the shelter's home page, requested at the same time, each with a timeout and a status check:

```javascript
async function photoOf(breed) {
  const response = await fetch(`https://dog.ceo/api/breed/${breed}/images/random`, {
    signal: AbortSignal.timeout(8000),
  });
  if (!response.ok) {
    throw new Error(`No photos of ${breed} (status ${response.status})`);
  }
  const data = await response.json();
  return data.message;
}

const breeds = ['corgi', 'dalmatian', 'samoyed'];
const photos = await Promise.all(breeds.map(photoOf));

breeds.forEach((breed, i) => console.log(`${breed}: ${photos[i]}`));
```

```text
corgi: https://images.dog.ceo/breeds/corgi-cardigan/n02113186_6300.jpg
dalmatian: https://images.dog.ceo/breeds/dalmatian/cooper2.jpg
samoyed: https://images.dog.ceo/breeds/samoyed/n02111889_13603.jpg
```

Your photos will be different: they're random. `map` starts all three requests, `Promise.all` waits for every one, and if any breed fails, the whole thing rejects with your own clear error. A module ago, almost none of that would have made sense. Now you can read it from top to bottom.

## Show what you can do: Trivia Night

Module 5's project is a game to play with friends on the couch: **Trivia Night**, with real questions from the internet.

![The Trivia Night game mid-round: a category and difficulty at the top, the question "What is the fastest land animal?", four shuffled answer buttons, a countdown ring showing 0:09, and the score, 4 of 6, in the corner](https://fsdtrainingmedia.blob.core.windows.net/public/images/2026/10/58570e9c3b6447ec8748c3ce9927f481.webp)

The project hands you the finished page and its look. You write the JavaScript:

- **Real questions:** fetch 10 questions from the free Open Trivia Database (no key needed), for the category and difficulty the players pick, with a query string such as `?amount=10&category=27&difficulty=easy`.
- **A loading state** while the questions are on their way.
- **Shuffled answers**, so the right one isn't always in the same place.
- **A 15-second countdown** for every question, with `setInterval`, that moves on when time runs out.
- **The score**, and the **best score** saved in the browser, so there's a record to beat.
- **A friendly failure:** when the trivia API is down, a clear message, a **Try again** button, and a local file of questions as a fallback, so the game still works offline.
- **Safe text:** the questions come with special characters encoded, as in `Thomson%E2%80%99s%20Gazelle`, so you'll decode them with `decodeURIComponent` and show them with `textContent`, never by putting the API's text in as HTML.

Pick a stretch goal if you like: a "50/50" button that removes two wrong answers, or a round of questions you write yourself about your friends.

## Which tool fits?

Most of the project, like most real work with asynchronous code, comes down to one question for each step: *which tool does this job?*

| The job | The tool |
|---|---|
| Do something once, after a delay | `setTimeout` |
| Do something again and again, such as a countdown | `setInterval`, stopped with `clearInterval` |
| Wait for one thing that takes time | a promise, with `await` inside an `async` function |
| Wait for several things, and need them all | `Promise.all` |
| Get data from a web API | `fetch`, then `response.json()` |
| Send data to a web API | `fetch` with `method: 'POST'`, a `Content-Type` header and `JSON.stringify` |
| Find out the server said "no" (a 404 or a 500) | `response.ok` and `response.status` |
| Handle no answer at all, or any thrown error | `try`/`catch` |
| Give up on a slow server | `AbortSignal.timeout` |
| Put things back however it ended, such as enabling a button | `finally` |

**Try it.** For each feature of Trivia Night, pick the tools from the table you think you'll need, and write them down. You'll find out how close you were when you build it.

## A sneak peek: a test that catches a bug before a player does

The countdown should show `0:15`, `0:14` and so on down to `0:00`. Here's a function that formats it, and a test for it, written with Node's own test tools, the same ones that have been checking your exercises:

```javascript
import { test } from 'node:test';
import assert from 'node:assert/strict';

// Shows the seconds left on a question's countdown, the way a game clock does.
function timeLeftText(seconds) {
  return `0:${seconds}`;
}

test('a countdown under 10 seconds still has two digits', () => {
  assert.equal(timeLeftText(15), '0:15');
  assert.equal(timeLeftText(5), '0:05');
});
```

Save it as `countdown.test.js` and run `node --test`, and the test fails. Among the lines it prints:

```text
✖ a countdown under 10 seconds still has two digits
  AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

  '0:5' !== '0:05'
```

`0:15` is right, but with 5 seconds left the clock would say `0:5`. A player would spot that in the middle of a game, and wonder what else is broken. The test spotted it first, in a few milliseconds, before anyone played. That's what a test is for: it's a smoke alarm that stays quiet until something is wrong. You've been running tests like this since Module 1. In Module 6 you start **writing** them.

## What Module 6 unlocks

Module 6, *Professional JavaScript*, is how JavaScript is built at work:

- **Tools professionals use:** npm and packages (an app store for code), Vite (a dev server that reloads the page as you type), and ESLint and Prettier, a spell-checker and a tidy-up for your code.
- **Testing your JavaScript:** writing your own tests with Vitest, including tests for errors, for async code and for a page.
- **Fast, safe and shipped:** keeping a page quick, keeping it safe from text that tries to sneak in as code, and putting your app online at a link anyone can open.

Its project is a **Typing Speed Game** with words per minute, accuracy and a high-score table, tested, tidy and online, so a friend can play it from a link you send them.

## Check yourself

2 questions to try on the lesson page.

## So what

Your code can now wait for the world, and cope when the world doesn't answer. Trivia Night is your chance to prove it, and Module 6 shows you how to build it the way professionals do, and share it with anyone.

## Key terms

- [Promise](https://www.ask-codey.com/glossary/promise)
- [Fetch API](https://www.ask-codey.com/glossary/fetch-api)
- [Event Loop](https://www.ask-codey.com/glossary/event-loop-javascript)
- [Unit Test](https://www.ask-codey.com/glossary/unit-test-javascript)

## Related

- [Waiting for Several Things at Once](https://www.ask-codey.com/lessons/javascript-promises-several-at-once)
- [Loading, Empty and Error States](https://www.ask-codey.com/lessons/javascript-fetch-loading-and-error-states)

Source: https://www.ask-codey.com/lessons/javascript-up-next-working-like-a-professional
