Checkpoint: Failure Policy

The Course
•
3 min read

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.

Predict, then run JavaScript
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 tryWhat your result should demonstrate
First reason null or undefinedStill record that a failure occurred
Later Error after first failureKeep the first exact reason
Fresh closure instanceStart 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

Exercise

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.

Your workspace JavaScript
// 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
true

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

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.

Was this article helpful?

Your response is saved on this device.