Start learning free

LESSON 40 OF 58 · FULL-STACK: WHEN THINGS GO WRONG

Too Slow

Practice

Not every failure is an error. Sometimes the shop just doesn't answer. fetch has no time limit of its own: it waits as long as the connection stays open. Meanwhile the Pay button stays disabled, and the visitor has no idea what is going on.

An AbortController lets the page give up on its own request. Its signal goes with the request, and its abort() cancels it. A cancelled fetch rejects with an error whose name is "AbortError":

const controller = new AbortController();
fetch("/api/products?q=mug", { signal: controller.signal })
  .catch((err) => console.log(err.name)); // AbortError
controller.abort();

To give up after a while, a setTimeout calls abort(). When the answer comes in time, clearTimeout cancels that timer. Otherwise it stays waiting long after its request is done.

In this lesson the shop's first POST /api/checkout gets no answer for 30 seconds. The check must print:

> click "Pay"
  request: POST /api/checkout {…} ... (the shop is slow: no answer for 30 s)
    button: Pay (disabled)
> 5000 ms pass
  request: POST /api/checkout {…} -> cancelled by the page
    button: Pay
    alert: This is taking too long
> click "Pay"
  request: POST /api/checkout {…} -> 201
> the page's timers still waiting to fire
  none

Your task: in client/src/api.js, give each request an AbortController and a 5 second timer that aborts it, and clear the timer in finally. Turn an AbortError into an ApiError with status 0 and the message "This is taking too long". A fetch that fails for another reason still says "Can't reach the shop".


Assignment
Follow the Coding Tutorial to give api() a time limit: the controller, its signal in fetch, the timer, clearTimeout in finally, and the message for an aborted request.


Hint
finally runs after try and after catch alike, so the timer is cleared whether the answer came or not. Check err.name above the line that throws "Can't reach the shop", and throw from inside the if.


STEP 1 OF 6
    Ctrl + Enter to check