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.
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 try | What your result should demonstrate |
|---|---|
| Five values in groups of two | Three yield requests and a correct sum |
| Empty input | No chunks and total zero |
| Cancellation before first chunk in an extension | Do 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
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.
// 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
3Explain 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.
Completion is saved in this browser only. It does not measure mastery.