JavaScript · API · Начальный

Пагинация

5 задач

Перебирайте страницы ответов API для сбора всех результатов.

Как работает пагинация

#
API возвращает результаты по 20 по умолчанию. Ответ включает `next` — полный URL следующей страницы или `null`, если вы на последней: ```javascript { count: 372, next: "https://apilearn.tukas.dev/api/products/?page=2", previous: null, results: [ /* 20 товаров */ ] } ``` Чтобы получить все товары, продолжайте переходить по `next`, пока он не станет `null`: ```javascript const BASE_URL = 'https://apilearn.tukas.dev'; async function getAllProducts() { let url = `${BASE_URL}/api/products/`; const all = []; while (url) { const response = await fetch(url); const data = await response.json(); all.push(...data.results); url = data.next; // null на последней странице → цикл завершается } return all; } ``` `...data.results` распределяет элементы страницы в массив `all`. `url = data.next` переходит к следующей странице. Когда `data.next` становится `null`, условие while ложно и цикл завершается. Можно также запросить больше результатов на страницу через `page_size`: ```javascript // 50 на страницу вместо 20 — нужно меньше запросов const params = new URLSearchParams({ page_size: 50 }); const response = await fetch(`${BASE_URL}/api/products/?${params}`); ``` Максимальное значение `page_size` — 100.

Паттерны пагинации

#
Собираем все продукты со всех страниц: ```javascript const BASE_URL = 'https://apilearn.tukas.dev'; async function getAllProducts() { let url = `${BASE_URL}/api/products/?page_size=100`; const all = []; while (url) { const response = await fetch(url); const data = await response.json(); all.push(...data.results); url = data.next; } console.log(`Загружено ${all.length} товаров`); return all; } getAllProducts(); ``` Пагинация с колбэком — обрабатываем каждую страницу по мере поступления: ```javascript const BASE_URL = 'https://apilearn.tukas.dev'; async function eachPage(baseUrl, callback) { let url = baseUrl; while (url) { const response = await fetch(url); const data = await response.json(); await callback(data.results, data.count); url = data.next; } } async function main() { await eachPage(`${BASE_URL}/api/products/`, (products, total) => { console.log(`Страница: ${products.length} / всего ${total}`); }); } main(); ``` Останавливаемся досрочно, найдя нужное: ```javascript const BASE_URL = 'https://apilearn.tukas.dev'; async function findProduct(name) { let url = `${BASE_URL}/api/products/`; while (url) { const response = await fetch(url); const data = await response.json(); const found = data.results.find(p => p.name === name); if (found) return found; url = data.next; } return null; } async function main() { const product = await findProduct('Tea Table Set with Three Chairs'); console.log(product ? product.price : 'не найдено'); } main(); ```

Справочник пагинации

#
**Форма пагинированного ответа** ```javascript { count: 372, // всего элементов на всех страницах next: "...?page=2" | null, previous: "...?page=1" | null, results: [...] // элементы текущей страницы } ``` **Параметры** ``` page Номер страницы (по умолчанию 1) page_size Элементов на страницу (по умолчанию 20, максимум 100) ``` **Паттерн сбора всех страниц** ```javascript async function collectAll(startUrl) { const all = []; let url = startUrl; while (url) { const response = await fetch(url); const data = await response.json(); all.push(...data.results); url = data.next; } return all; } ``` **Уменьшение количества запросов через page_size** ```javascript // 372 товара по 20 за запрос = 19 запросов // 372 товара по 100 за запрос = 4 запроса new URLSearchParams({ page_size: 100 }) ``` **Проверка наличия следующих страниц** ```javascript if (data.next) { /* есть ещё страницы */ } if (!data.next) { /* последняя страница */ } ```
01

Получить 2-ю страницу

#

Получите 2-ю страницу `/api/products/` с помощью параметра `page`. Выведите количество результатов на этой странице и название первого товара.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // fetch 2-й страницы и вывести results.length + название первого товара
}

main();
Решение
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const params = new URLSearchParams({ page: 2 });
  const response = await fetch(`${BASE_URL}/api/products/?${params}`);
  const data = await response.json();
  console.log(data.results.length);
  console.log(data.results[0].name);
}

main();
02

Следовать по next для сбора всех страниц

#

Напишите цикл, который переходит по `data.next`, пока он не станет `null`. Подсчитайте общее количество товаров на всех страницах и выведите результат.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  let url = `${BASE_URL}/api/products/`;
  let total = 0;

  // цикл: fetch url, добавить к total, url = data.next
}

main();
Решение
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  let url = `${BASE_URL}/api/products/`;
  let total = 0;

  while (url) {
    const response = await fetch(url);
    const data = await response.json();
    total += data.results.length;
    url = data.next;
  }

  console.log(total);
}

main();
03

Собрать все товары в массив

#

Напишите функцию `getAllProducts()`, которая пагинирует все страницы с `page_size=100` и возвращает плоский массив всех товаров. Выведите общую длину.

const BASE_URL = 'https://apilearn.tukas.dev';

async function getAllProducts() {
  // пагинация с page_size=100, вернуть плоский массив
}

async function main() {
  const all = await getAllProducts();
  console.log(all.length);
}

main();
Решение
const BASE_URL = 'https://apilearn.tukas.dev';

async function getAllProducts() {
  let url = `${BASE_URL}/api/products/?page_size=100`;
  const all = [];

  while (url) {
    const response = await fetch(url);
    const data = await response.json();
    all.push(...data.results);
    url = data.next;
  }

  return all;
}

async function main() {
  const all = await getAllProducts();
  console.log(all.length);
}

main();
04

Найти самый дорогой товар

#

Загрузите все товары (пагинируйте все страницы), затем найдите тот с наибольшей ценой. Выведите его название и цену.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // собрать все товары по страницам
  // найти самый дорогой
}

main();
Решение
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  let url = `${BASE_URL}/api/products/?page_size=100`;
  const all = [];

  while (url) {
    const response = await fetch(url);
    const data = await response.json();
    all.push(...data.results);
    url = data.next;
  }

  const mostExpensive = all.reduce((max, p) =>
    parseFloat(p.price) > parseFloat(max.price) ? p : max
  );
  console.log(mostExpensive.name, mostExpensive.price);
}

main();
05

Подсчёт товаров на каждой странице

#

Получите все страницы `/api/products/` с размером страницы по умолчанию. Для каждой выведите `"Страница N: X товаров"`. В конце выведите общую сумму.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  let url = `${BASE_URL}/api/products/`;
  let page = 1;
  let total = 0;

  // перебирать страницы и выводить информацию
}

main();
Решение
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  let url = `${BASE_URL}/api/products/`;
  let page = 1;
  let total = 0;

  while (url) {
    const response = await fetch(url);
    const data = await response.json();
    console.log(`Page ${page}: ${data.results.length} products`);
    total += data.results.length;
    url = data.next;
    page++;
  }

  console.log(`Total: ${total} products across ${page - 1} pages`);
}

main();