Create a small failure recorder for one operation. The first record call owns the result; later calls cannot replace it. A separate hasFailed flag distinguishes no failure from a failure whose value is undefined.
This is the same distinction the pool needs when callbacks can throw arbitrary JavaScript values. A default error variable initialized to null and checked for truthiness would lose important cases. The recorder itself does not start work or cancel anything; it isolates the failure-selection policy.
Test a normal Error, a string and undefined as first values. Then attempt to replace each with a later error. Do not claim “first error wins” unless your program records the first observed failure independently of its truthiness.
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.
let failed = false;
let failure;
function record(error) {
if (!failed) {
failed = true;
failure = error;
}
}
record(undefined);
record("later");
console.log(failed);
console.log(failure === undefined);Check your prediction
true
true Acceptance cases before you code
Write a small test plan before implementing first failure preservation. 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 |
|---|---|
| First reason null or undefined | Still record that a failure occurred |
| Later Error after first failure | Keep the first exact reason |
| Fresh closure instance | Start with no failure and no shared state |
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: Failure Policy: practise
Write createFailure() returning record, hasFailed and getFailure functions backed by a closure. Record null, then a later Error. Print true and true for hasFailed() and getFailure() === null.
// Use a separate boolean to track whether the first observation happened.Hint 1: the idea
The stored value is not a reliable presence flag.
Hint 2: a first step
Only the first record call should assign the failure and change the flag.
Show one solution
function createFailure() {
let failed = false;
let failure;
return {
record(error) {
if (!failed) {
failed = true;
failure = error;
}
},
hasFailed() {
return failed;
},
getFailure() {
return failure;
}
};
}
const state = createFailure();
state.record(null);
state.record(new Error("later"));
console.log(state.hasFailed());
console.log(state.getFailure() === null);true
trueExplain 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
Test no record calls, first undefined, first false and first Error. For each, distinguish whether a failure exists from what its value is. Explain when wrapping a failure in TaskError changes the public contract and when preserving an external abort reason is preferable.
Completion is saved in this browser only. It does not measure mastery.