Each page of the storefront called fetch and response.json() on its own, and none of them checked the status. But fetch only fails when no answer comes at all: a 409 or a 503 is still an answer, and its error object reached the page as if it were data. In this lesson, every call to the API goes through one door, the function api in client/src/api.js.
api(path, options) sends the method and the body as JSON, reads the answer as JSON, and checks response.ok (true for 200 to 299). For an answer that isn't ok, it throws an ApiError that carries the status and the server's message. The pages catch it with err instanceof ApiError.
An error class of your own extends Error. Its constructor must call super(...) before it uses this. For example:
class OutOfStock extends Error {
constructor(product) {
super(product + " is out of stock");
this.product = product;
}
}
The check must print:
> open the page
request: GET /api/products -> 200
text: 8 products
> click "Send suggestion" (with Mug)
request: POST /api/suggestions {"name": "Mug"} -> 409
status: We already sell Mug
> click "Send suggestion" (with Kettle)
request: POST /api/suggestions {"name": "Kettle"} -> 201
status: Thanks! We got your suggestion: Kettle
> the API will answer GET /api/products with 503
> reload the page
request: GET /api/products -> 503
alert: The shop is closed for stock-taking (status 503)
Your task: in client/src/api.js, write getProducts() on top of api. Make api send and read JSON and throw an ApiError for an answer that isn't ok. Give ApiError a constructor that keeps the message, the name and the status.
Assignment
Follow the Coding Tutorial to build getProducts, the function api, and the class ApiError, so that both pages show the server's own words when something goes wrong.
Hint
Throw the error between reading data and returning it. In the constructor, super(message) comes before any line that uses this.
Free plan: 30 tutor messages. PRO is unlimited.
