Start learning free

LESSON 132 OF 173 · BACKEND: SPEED

Project: A Fast Product List in JavaScript

Practice

This project puts the module together in the shop's busiest route, GET /products. Earlier lessons made the list ask only for id, name, price and read one keyset page at a time with ?after=. Two things are still missing: clients can't choose the page size, and the list lost its cache when it got pages.

A size with a limit: clients will pick the size with ?size=, but only up to a limit. Without one, a single request for ?size=1000000 reads and sends the whole table, and the pages were for nothing. Read the number with a default, and refuse anything out of range with 400, like this route for reviews does:

app.get("/reviews", (req, res) => {
  const count = Number(req.query.count || 10);
  if (!Number.isInteger(count) || count < 1 || count > 20) {
    return res.status(400).json({ error: "count must be between 1 and 20" });
  }
  ...
});

One cache entry per page: a single answer kept in cache.products would be handed out for every page. Each page needs its own cache key, built from everything that decides its content: after and size, as in "6:3". So cache.products becomes an object with one property per page. The routes that change products already run delete cache.products;, which now forgets every page at once.

On a fresh shop, these requests, in this order, must get these answers:

GET /products  →  200  {"next_after": 3, "products": [{"id": 1, "name": "Mug", "price": 12}, …]}
GET /products?size=5  →  200  {"next_after": 5, "products": [… 5 products, ids 1 to 5 …]}
GET /products?after=6  →  200  {"next_after": null, "products": [{"id": 7, "name": "Stapler", …}, {"id": 8, …}]}
GET /products?after=6  →  200  the same page, from the cache
GET /debug/queries  →  200  {"queries": 3}
POST /products {"name": "Cup", "price": 8}  →  201  {"id": 9, "name": "Cup", "price": 8}
GET /products?after=6  →  200  {"next_after": 9, "products": [{"id": 7, …}, {"id": 8, …}, {"id": 9, "name": "Cup", "price": 8}]}
GET /products?size=6  →  400  {"error": "size must be between 1 and 5"}
GET /products?size=0  →  400  {"error": "size must be between 1 and 5"}
GET /debug/queries  →  200  {"queries": 5}

Your task: add a constant MAX_PAGE_SIZE set to 5. Read size with PAGE_SIZE as the default, and answer 400 when it is not a whole number from 1 to 5. Write the page query the starting code lost again, with LIMIT set to size, keep the answer in a constant, and cache each page under its own key for CACHE_SECONDS.


Assignment
Follow the Coding Tutorial to add a page size limit to GET /products and give each page its own cache entry.


Hint
Build the key from both after and size, joined with + and a ":" between them. Check the size before you make the key, so a refused size never runs a query or fills a cache entry.


STEP 1 OF 12
    Ctrl + Enter to check

    Speed Project in JavaScript

    Keep going with JavaScript1,600+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free