Your export button turns green. The API returned 202. The worker has not produced a file.
That screen may be reporting a success your system has not observed yet.
Here is a hypothetical implementation:
const response = await fetch("/exports", { method: "POST" });
if (!response.ok) throw new Error("Export request rejected");
showToast("Your export is ready");
The last line silently changes the meaning of the response. HTTP 202 means the request was accepted for processing. Processing may be incomplete or may not have started, and it can still fail. A successful HTTP response is insufficient evidence that this particular file exists.
Give the button a job lifecycle
For this export feature, use distinct application states: submitting, queued, running, completed and failed. Add a state for losing the ability to observe the job. That last state matters when the browser loses its connection while a worker continues.
These are proposed product states, not extra meanings assigned to the HTTP status code. Your backend must define how the client observes them: a status resource, events, or another documented mechanism.
An illustrative response contract could be:
{
"jobId": "export-demo-17",
"state": "queued",
"statusUrl": "/exports/export-demo-17"
}
Those field names are specific to the example. HTTP 202 does not automatically supply a status endpoint.
Make each claim depend on evidence
“Request received” can follow acceptance. “Preparing your file” needs a known active job. “Download ready” needs a completed result the user can access.
If a status request fails, keep the job identifier. Show that its state cannot currently be checked and let the user check again. Creating another export immediately can duplicate work and leave two jobs whose results are difficult to distinguish.
Refreshing the page is another useful rehearsal. Does the screen reconnect to the original job, forget it, or start over? Decide that behavior before shipping the optimistic toast.
Test the promise made by the interface
I would use a controlled service with these outcomes:
- acceptance followed by completion;
- acceptance followed by worker failure;
- acceptance followed by a lost status response;
- page reload while the job is queued;
- a completed job whose download is no longer available.
For every case, compare the visible message with the state the application actually knows. Include a check that observation failure never becomes a “ready” badge.
The interesting review artifact is a short sequence of observations: accepted response, job state, final result, visible copy. A screenshot of the green toast by itself cannot establish that an export worked.
Which part of your product currently uses “success” for a request that only entered a queue?
Top comments (0)