Checkpoint: Responsive Work

The Course
•
3 min read

A promise created with Promise.resolve does not necessarily yield to the browser’s task queue; long chains of microtasks can still starve other tasks. For a teaching example, awaiting a short timer gives the event loop an opportunity to process another task between chunks.

Chunking does not make CPU work parallel or guarantee a particular UI frame rate. It changes scheduling opportunities. Choose chunk size based on measurements and test final correctness independently of timing. A worker can keep CPU-heavy work off the page, but this course’s editor itself runs in a worker, so no DOM rendering should be inferred from this console example.

Implement a chunked total that yields after each chunk. Use a counter to prove the intended number of yield requests; do not predict wall-clock duration. Cancellation checks can be added between chunks, but cannot interrupt one synchronous chunk halfway through.

Predict, run, and explain

Write the output and trace the important state changes before checking it. Then run the program. Each editor is independent. Async examples end with main() so this editor waits for their work.

Predict, then run JavaScript
async function main() {
  console.log("before");
  await new Promise(resolve => setTimeout(resolve, 0));
  console.log("after");
}

main();
Check your prediction
before
after

Acceptance cases before you code

Write a small test plan before implementing chunked calculation and scheduling. These cases extend the brief; they are not a second worked solution. Predict the expected behavior independently, then test through the public function. A good ordinary example and a good boundary example should catch different possible mistakes.

Case to tryWhat your result should demonstrate
Five values in groups of twoThree yield requests and a correct sum
Empty inputNo chunks and total zero
Cancellation before first chunk in an extensionDo not perform the first chunk

After the core task passes, deliberately break one rule and identify the case that notices it. Restore the implementation and explain the failure in terms of the contract, not the number of assertions. If a case requires a concept you have not recalled, revisit the relevant lesson before opening the solution.

Your turn

Exercise

Checkpoint: Responsive Work: practise

Sum [1,2,3,4,5] in chunks of 2. Await a zero-delay timer after each processed chunk and count those yield requests. Print 15 and 3. Keep the full calculation inside async main.

Your workspace JavaScript
// Three chunks are processed: two pairs and one final single value.
Hint 1: the idea

Use a numeric accumulator separate from the scheduling counter.

Hint 2: a first step

Advance start by 2 and slice the next group.

Show one solution
async function main() {
  let total = 0;
  let yields = 0;
  const values = [1, 2, 3, 4, 5];

  for (let start = 0; start < values.length; start += 2) {
    for (const value of values.slice(start, start + 2)) {
      total += value;
    }

    yields++;
    await new Promise(resolve => setTimeout(resolve, 0));
  }

  console.log(total);
  console.log(yields);
}

main();
15
3

Explain why the implementation meets the stated contract. Which part is enforced by the language or checker, and which part needs behavioral evidence?

Change it and test it

Add signal.throwIfAborted before each chunk and test a pre-aborted signal. Compare larger chunk sizes locally, reporting both total correctness and observed responsiveness. Explain why a tight infinite loop cannot notice an abort event while it monopolizes its thread.

Was this article helpful?

Your response is saved on this device.