Describe Loading, Cancellation and Late Results Before an Agent Changes the UI
Drafted and reviewed using AI assistance.
On this page
Describe asynchronous UI behavior as an ordered set of events: what the user selected, which request belongs to that selection and what the screen should show when a result arrives. Include the case where the user returns to the same item before an older request finishes.
That gives a coding agent a behavior contract to inspect. A request to “fix the spinner” does not say which result may replace the page, which error may appear or when a loading indicator should stop.
Choose one concrete interaction
Imagine a fictional project-preview panel. Selecting a project starts read-only preview work. For this example, each selection starts a new request; there is no implicit cache reuse. A new selection clears the previous preview and shows a loading message naming the selected project.
The six events below are original illustrative requirements, not a reproduced defect or an execution log. We deliberately stipulate that an old application-level completion event arrives after cancellation was requested. No request implementation is supplied, and the example does not claim that an aborted fetch must later fulfill.
Write the six-event timeline
| Event | What happens | Active view owner | Expected visible state |
|---|---|---|---|
| E1 | User selects A; request p1 starts | A / p1 | Loading A; no preview yet |
| E2 | User selects B; request p2 starts | B / p2 | Clear A's preview area; show Loading B |
| E3 | Application requests cancellation of old p1; no stop confirmation is established | B / p2 | Keep Loading B; do not show a B error or clear its loading state |
| E4 | p2 completes before p1 | B / p2 | Show B's preview; B is no longer loading |
| E5 | User selects A again; new request p3 starts | A / p3 | Clear B's preview area; show Loading A for p3 |
| E6 | Old p1 completion arrives | A / p3 | Ignore p1 for the visible view; keep Loading A for p3 |
The completion order is p2 before p1. At E6, checking only the selected project would be insufficient: both the old p1 and the new p3 concern A.
The result must belong to the active request, not just an item with the same name. In this case, a completion may fill the panel only when it matches the active project and request, and that request is still eligible to complete the view.
Separate three meanings of “cancel”
MDN's AbortController documentation describes communicating with asynchronous work through AbortSignal and aborting supported browser operations. It does not supply the product policy for this panel. The visible-state rules here are our example's design choices.
| Action | Requirement it can express | What must not be assumed |
|---|---|---|
| Request cancellation | Ask the relevant operation to stop using its supported mechanism | Every producer has stopped, or a server-side change has been reversed |
| Discard a result | Prevent an obsolete completion from changing the current view | The producer did no work or a remote operation never completed |
| Reverse a completed server action | Perform a separate supported operation to restore some state | A browser abort or ignored response automatically performs that reversal |
This panel is read-only. If your real request saves or changes remote data, establish that operation's status and reversal contract separately. Hiding its result is a display decision, not evidence that its effect was undone.
Define ownership for each state
| Incoming action or event | Ownership condition | Expected view behavior |
|---|---|---|
| Start a selection | New active project/request pair | Clear previous preview and show named loading state |
| Active request succeeds | Same active pair, still pending | Show its preview and finish its loading state |
| Active request fails | Same active pair, still pending | Show that request's error and finish its loading state |
| Request cancellation of an older request | Request is no longer the active owner | Keep the active request's state unchanged |
| User stops the active request | Explicitly mark that request ineligible to complete the view | Show Preview stopped for the selected project; no result is installed |
| Completion after an active stop | Stopped request is no longer eligible | Keep the stopped state; do not repopulate the panel |
| Old success or old error | Does not own the active pending view | Do not replace content, show its error or stop the active spinner |
| Old cleanup notification | Belongs to an obsolete request | Do not clear another request's loading state |
“Preview stopped” describes the chosen UI state. If stopping the producer is unconfirmed, do not turn that label into a promise that all background work has ceased.
These rules also cover a late failure. An error from p1 should not appear as a failure of p3 merely because the user is looking at A again.
State the policy choices instead of hiding them
Several behaviors are reasonable in different products. For this example, the choices are explicit:
| Decision | Alternative | Chosen policy and reason |
|---|---|---|
| Previous content during a new request | Keep it visible with a clear previous-result label | Clear it, so this compact panel has one visible owner |
| Starting B while A is stopping | Wait for a stop confirmation | Start B without waiting; isolate its view from old events |
| Returning to A | Reuse an explicitly identified cached result | Start p3; no cache policy is defined in this exercise |
| Stopping the active preview | Keep accepting its eventual completion | Mark it ineligible, so the stop action has a stable visible outcome |
The alternative policies are not defects. A coding agent needs to know which one the product intends before it changes the state handling.
Turn a symptom into an observable request
A fictional spoken description might be:
“I click A, then B, and things come back in a strange order. Sometimes I go back to A. Make the screen keep the right preview.”
The implementation-neutral request is more precise:
Task: make the project-preview panel follow its active request.
Use the six-event sequence E1–E6 as an expected behavior case.
The selected item alone is not sufficient identity: p1 and p3 both
refer to A, but only p3 owns the final pending view.
Chosen behavior:
- Each selection starts a new request; no implicit cache reuse.
- Clear the previous preview and show Loading [selected project].
- Install a success/error only for the active, eligible pending request.
- An old completion, error or cleanup event cannot replace the current
preview or change its loading/error state.
- A deliberate stop of the active request shows Preview stopped and
makes that request ineligible to fill the view later.
- Request stopping obsolete work using the mechanism actually supported.
Do not describe a stop request as a confirmed server rollback.
Preserve:
The selection controls and preview content format.
Do not add an undo feature, change server-side data or redesign navigation.
Return:
The current event/ownership path, a focused change proposal and a check
record for the event cases. Record the actual implementation assumptions;
keep unperformed checks separate from observed behavior.
Check the event order, not just one screenshot
| Proposed check | Expected outcome | Actual observation |
|---|---|---|
| Deliver p2, then old p1 after E5 | B displays at E4; at E6 p1 does not replace or finish p3's pending view | — |
| Deliver an old p1 error instead of success | No current p3 error is installed | — |
| Deliver old p1 cleanup while p3 is pending | p3 remains visibly loading | — |
| Stop active p3, then deliver p3 completion | Stopped state remains; no preview is installed | — |
| Deliver active p3 success without a stop | A's p3 preview appears and its loading state finishes | — |
All outcomes are manual expectations. The producer, cancellation support, event routing, cache behavior and any remote side effects remain implementation questions until inspected. None was exercised for this guide.
A useful request names the visible owner at each step. That lets the implementation solve the actual sequencing problem while keeping cancellation, display policy and reversal of completed actions separate.