JavaScript · API · Beginner

Your First Request

5 tasks

Make your first HTTP request with fetch and read the JSON response.

Making HTTP requests with fetch

#
In this section, we'll practice on a special website I created for this purpose. This website is a fake online store that functions exactly like a real one. It has a standard browser user interface and full coverage of all capabilities via the RESTful API. Below, I'll provide several links so you can visit this website and familiarize yourself with it before working on the materials and exercises in this section: The website's main page with information about it: [https://apilearn.tukas.dev/](https://apilearn.tukas.dev/) Specially created detailed documentation for its API (don't worry, you'll start to understand it soon): [https://apilearn.tukas.dev/api/docs/](https://apilearn.tukas.dev/api/docs/) Okay, now that we've briefly explored the website, let's move on to learning how to work with the API. `fetch` is JavaScript's built-in function for making HTTP requests. When you call it, the browser sends a request to the server -- but the server's response takes time. JavaScript handles this with **asynchronous execution**: instead of freezing the whole program while waiting, `fetch` returns a **Promise** -- an object that will hold the response once it arrives. The cleanest way to work with Promises is `async/await`. Mark a function with `async`, then use `await` to pause it until a Promise resolves. The rest of your program keeps running: ```javascript async function main() { const response = await fetch('https://apilearn.tukas.dev/api/products/'); const data = await response.json(); console.log(data); } main(); ``` With `fetch` you always need **two `await` calls**: ```javascript const response = await fetch(url); // 1st await: wait for the server to reply const data = await response.json(); // 2nd await: read and parse the body ``` Why two? `fetch` resolves as soon as the server sends the **headers** -- before the body arrives. Calling `response.json()` starts reading the body, which is a second async operation. The `response` object between the two awaits has useful properties: ```javascript console.log(response.status); // 200, 404, 500, ... console.log(response.ok); // true if status is 200-299 console.log(response.url); // final URL after any redirects ``` `response.ok` is the key property for error checking -- `true` for any 2xx status, `false` for 4xx/5xx. Unlike `axios`, plain `fetch` never throws on HTTP errors -- you always get a `response` object back.

Reading the response

#
A complete example that fetches the product list and reads its fields: ```javascript const BASE_URL = 'https://apilearn.tukas.dev'; async function main() { const response = await fetch(`${BASE_URL}/api/products/`); const data = await response.json(); console.log('Status:', response.status); // 200 console.log('Total products:', data.count); // 372 console.log('On this page:', data.results.length); // 20 const first = data.results[0]; console.log(first.name, first.price); console.log(first.category.name); // category is an object: {id, name, slug} } main(); ``` Fetch a single product by id: ```javascript const BASE_URL = 'https://apilearn.tukas.dev'; async function getProduct(id) { const response = await fetch(`${BASE_URL}/api/products/${id}/`); const product = await response.json(); console.log(product.name); // "Tea Table Set with Three Chairs" console.log(product.price); // "150.00" (string) console.log(product.sell_price); // "135.00" (after discount) console.log(product.slug); // "tea-table-set-three-chairs" console.log(product.category.name); // "Kitchen" console.log(product.category.slug); // "kitchen" return product; } async function main() { const p = await getProduct(1); console.log(p); } main(); ``` Note that `price` is a string, not a number. Use `parseFloat(product.price)` if you need to do math with it.

fetch and Response quick reference

#
**fetch(url, options)** ```javascript fetch(url) // GET request fetch(url, { method: 'POST', body: JSON.stringify(data), headers: { 'Content-Type': 'application/json' } }) ``` **Response properties** ``` response.status number HTTP status code (200, 404, ...) response.ok boolean true if status 200-299 response.url string Final URL after redirects response.headers Headers Response headers object ``` **Response methods** ``` await response.json() Parse body as JSON → object await response.text() Parse body as plain text → string ``` **Always two awaits** ```javascript const response = await fetch(url); // wait for headers const data = await response.json(); // wait for body ``` **Product object fields** ``` id number Numeric id name string Product name slug string URL-friendly identifier price string e.g. "150.00" — convert with parseFloat() sell_price string Price after discount discount string Discount amount quantity number Stock quantity category object {id, name, slug} image string Image URL ```
01

Fetch the product list

#
Use `fetch` to GET `/api/products/`. Print the total number of products (`count`) and how many results are on the first page.
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // 1. fetch /api/products/
  // 2. print count and results.length
}

main();
Solution
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const response = await fetch(`${BASE_URL}/api/products/`);
  const data = await response.json();
  console.log(data.count);
  console.log(data.results.length);
}

main();
02

Fetch a single product

#
Fetch the product with id 1 from `/api/products/1/`. Print its `name`, `price`, and `slug`.
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // GET /api/products/1/
  // print name, price, slug
}

main();
Solution
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const response = await fetch(`${BASE_URL}/api/products/1/`);
  const product = await response.json();
  console.log(product.name);
  console.log(product.price);
  console.log(product.slug);
}

main();
03

Check response.status and response.ok

#
Fetch `/api/products/99999/` (a product that does not exist). Print the `status` code and the value of `response.ok`. Then fetch `/api/products/1/` and do the same.
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // Fetch a missing product — check status and ok
  // Fetch a real product — check status and ok
}

main();
Solution
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const r1 = await fetch(`${BASE_URL}/api/products/99999/`);
  console.log(r1.status, r1.ok);  // 404 false

  const r2 = await fetch(`${BASE_URL}/api/products/1/`);
  console.log(r2.status, r2.ok);  // 200 true
}

main();
04

Fetch categories

#
Fetch `/api/categories/`. Print the total number of categories and the `name` of each one.
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // GET /api/categories/ and print count + each name
}

main();
Solution
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const response = await fetch(`${BASE_URL}/api/categories/`);
  const data = await response.json();
  console.log(data.count);
  for (const cat of data.results) {
    console.log(cat.name);
  }
}

main();
05

Fetch the first product name from the list

#
Fetch `/api/products/`, take the first result from `results`, and print its name and price. Convert the price to a number with `parseFloat` and print it as a float too.
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // fetch products, get first result, print name, price string, and parsed price
}

main();
Solution
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const response = await fetch(`${BASE_URL}/api/products/`);
  const data = await response.json();
  const first = data.results[0];
  console.log(first.name);
  console.log(first.price);
  console.log(parseFloat(first.price));
}

main();