A concurrent mapper has two orderings: when inputs are assigned to jobs, and when those jobs complete. A useful map API returns output in input order. Using results.push as each job completes instead records completion order, which can silently associate results with the wrong inputs.
Assign an index before awaiting, then write the result into that position. Tests should deliberately complete the second job before the first. A deferred promise is a promise whose resolve function you retain for test-controlled completion; it lets you choose an ordering without guessing a timer delay.
Today’s exercise coordinates two already-started jobs, not the full worker pool. It isolates the ordering contract so you can identify that defect later in a larger implementation. Keep a test that distinguishes indexed placement from push.
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() {
let resolveFirst;
const first = new Promise(resolve => {
resolveFirst = resolve;
});
const second = Promise.resolve("B");
const work = Promise.all([first, second]);
resolveFirst("A");
console.log((await work).join(","));
}
main();Check your prediction
A,B Acceptance cases before you code
Write a small test plan before implementing controlled output ordering. 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 |
|---|---|
| Second job completes first | Final values still use input positions |
| First job completes first | Ordinary ordering also works |
| Both callbacks observed | Await actual collector work before asserting the result |
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: Ordered Work: practise
Create two controlled promises. Register callbacks that write each completed value into its original index. Resolve the second as B before the first as A. Await both and print A,B.
// Explicitly retain both resolve functions; do not use timers to guess completion order.Hint 1: the idea
Reserve positions from input identity rather than completion timing.
Hint 2: a first step
Use results[0] for the first promise and results[1] for the second.
Show one solution
async function main() {
let resolveFirst;
let resolveSecond;
const first = new Promise(resolve => {
resolveFirst = resolve;
});
const second = new Promise(resolve => {
resolveSecond = resolve;
});
const results = [];
const a = first.then(value => {
results[0] = value;
});
const b = second.then(value => {
results[1] = value;
});
resolveSecond("B");
resolveFirst("A");
await Promise.all([a, b]);
console.log(results.join(","));
}
main();A,BExplain 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
Replace indexed writes with push and confirm the result becomes B,A. Restore the correct version. Extend to three jobs and two different completion schedules. Explain why an ordinary happy-path test might miss this defect.
Completion is saved in this browser only. It does not measure mastery.