Apply the ownership rule to previews
Write createPreview(load, publish), returning an async show(key) function. Each call publishes “loading”. Only the latest call may publish its resolved string or caught error message. An older completion must remain invisible, even if it fails. This small brief does not require cancellation or disposal; those are extension requirements.
Use two deferred promises to complete the newer request first and the older one last. Record publications in an array. Check the final publication and confirm the old value is absent. Repeat with an old rejection after a newer success. Looking only at the happy path does not verify the contract.
The starter supplies deferred so you can concentrate on ownership. Spend the checkpoint time on the first ordering test; if you need more time for the rejection variation, finish it before moving on. Never replace a controlled schedule with “wait 500 ms and hope.”
Predict and trace
Write the output before running. Follow the values through each call; if your prediction differs, identify the first step that surprised you.
let current = 0;
const old = ++current;
const recent = ++current;
console.log(old === current);
console.log(recent === current);Check your prediction
false
trueA generation identifies intent order independently of finish order.
Acceptance cases before you code
Write a small test plan before implementing latest preview lifetime. 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 |
|---|---|
| Newer success before older success | Keep the newer displayed value |
| Older failure after newer success | Ignore the stale failure too |
| Old completion while the newer request is loading | Do not publish the stale result or end the newer loading 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.
Build it yourself
Checkpoint: Preview Requests: practise
Implement createPreview and run the newer-success-before-older-success scenario. Print the recorded messages, ending in new.
function deferred() {
let resolve;
const promise = new Promise(done => {
resolve = done;
});
return { promise, resolve };
}
// Add createPreview and an ordering test.Hint 1: the idea
Capture a token before awaiting, then guard both success and catch publications.
Hint 2: a first step
Keep the counter inside createPreview and increment it for each show call.
Show one solution
async function main() {
function deferred() {
let resolve;
const promise = new Promise(done => {
resolve = done;
});
return { promise, resolve };
}
function createPreview(load, publish) {
let generation = 0;
return async function show(key) {
const mine = ++generation;
publish("loading");
try {
const value = await load(key);
if (mine === generation) {
publish(value);
}
} catch (error) {
if (mine === generation) {
publish(error.message);
}
}
};
}
const old = deferred();
const recent = deferred();
const messages = [];
const show = createPreview(
key => (key === "old" ? old.promise : recent.promise),
text => messages.push(text)
);
const a = show("old");
const b = show("recent");
recent.resolve("new");
await b;
old.resolve("old");
await a;
if (messages.includes("old")) {
throw new Error("stale publication");
}
console.log(messages.join(", "));
}
main();loading, loading, newExtend deferred with reject and test stale failure. Then specify cancel: it must invalidate a token even when no new show call replaces it.
Test a changed requirement
Extend deferred with reject and test stale failure. Then specify cancel: it must invalidate a token even when no new show call replaces it.
Explain before moving on
Why is guarding only the success path incomplete? Does ignoring a stale result stop the underlying request?
Completion is saved in this browser only. It does not measure mastery.