마지막 검색이 먼저 도착한다면
Latest Request Wins
응답 순서가 뒤집혀도 사용자의 최신 의도를 화면에 유지합니다.
GitHub에서 원문 보기 ↗새 탭TRY THE FAILURE CASE
먼저 보낸 요청이 늦게 끝난다면?
A · “layout”
B · “motion”
B의 응답을 기다리고 있어요.
B를 먼저 완료한 뒤 A를 완료해 보세요.
응답 순서를 직접 바꾸는 로컬 시뮬레이션입니다.
Repository Boundary
Prevent an older read response from replacing the result of a newer user intent. This pattern belongs to Design Engineering and adds no Layout CSS or shared store implementation.
Reusable Method
Use for replaceable reads such as search and selected-item detail. Do not use this policy to discard the outcomes of independent writes that all matter.
State Model And Ownership
The read owner stores a monotonically increasing identity, status, and last accepted result. Both success and failure must match the current request. Cancellation is an optional resource optimization; identity decides acceptance.
Transitions
| Event and precondition | Next state | Effect or invariant |
|---|---|---|
| Start read | Pending with new ID | Previous IDs lose authority |
| Matching success | Ready with results | Accept only current intent |
| Matching failure | Error | Preserve or clear old results under explicit policy |
| Stale success or failure | Unchanged | No status, result, or error mutation |
| Dispose | Disposed and invalidated | Ignore all pending outcomes |
Minimal Executable Example
Run this standalone JavaScript block with Node.js 22 or newer, or run all pattern examples from a repository checkout with npm run test:state-management. The assertions exercise the local model, not a browser or backend.
import assert from "node:assert/strict";
let serial = 0, active = 0, status = "idle", result = null;
const begin = () => { active = ++serial; status = "pending"; return active; };
function settle(id, ok, value) {
if (id !== active) return;
status = ok ? "ready" : "error";
if (ok) result = value;
}
const a = begin(), b = begin();
settle(b, true, "B");
settle(a, true, "A");
settle(a, false, "old failure");
assert.equal(result, "B");
assert.equal(status, "ready");
const c = begin();
active = ++serial; status = "disposed";
settle(c, true, "C");
assert.equal(status, "disposed");What Breaks If Removed
Remove the ID check: resolve B then A and the screen displays A under B's query. Guarding success only still allows A's error or finally handler to clear B's pending status.
Composition And Substitution
Combine URL state for committed query inputs and ID selection for detail. Use single flight for duplicate writes rather than silently discarding their acknowledgements.
Opinionated Guidance
Choose whether old results stay visible while refreshing and label their query identity. Debouncing reduces starts but does not establish response ordering.
Platform-Specific Guidance
Check identity after each awaited stage, including body decoding or transformations. Dispose invalidation and listener cleanup belong to the framework adapter.
Unsupported Absolutes
Latest-wins prevents this local overwrite; it does not guarantee fresh server data, cache coherence, or distributed consistency.
Verification Contract
- Start A then B; resolve B then A, including an A failure.
- Start B while A is pending; A completion must not clear B's pending indicator.
- Dispose before completion; no displayed state may update.
Record actual outcomes separately using the verification matrix.
Source, License, And Attribution
Locally authored synthesis and examples. No upstream implementation is copied. These experimental contracts describe consumer-owned behavior; review when a failure, ownership change, or platform change invalidates an assumption.
IA Navigation
Parent: State Management. Next: Continue the state management route.