JavaScript · API · Advanced

Parallel Requests with Promise.all

5 tasks

Use Promise.all to make concurrent API requests and speed up multi-call scripts.

Async requests and Promise.all

#
By default, `await` makes requests one at a time — each waits for the previous to finish: ``` fetch product 1 → wait → fetch product 2 → wait → ... ``` With `Promise.all`, multiple requests fire simultaneously: ``` fetch product 1 ┐ fetch product 2 ├→ all run at once → wait for all fetch product 3 ┘ ``` Basic usage — pass an array of Promises, get an array of results back: ```javascript const [products, categories] = await Promise.all([ fetch('https://apilearn.tukas.dev/api/products/').then(r => r.json()), fetch('https://apilearn.tukas.dev/api/categories/').then(r => r.json()), ]); console.log(products.count, categories.length); ``` Results come back in the same order as the input array — `products` is always index 0, `categories` is always index 1. `Promise.all` rejects immediately if **any** promise rejects. If you want to handle partial failures, use `Promise.allSettled`: ```javascript const results = await Promise.allSettled([ fetch(url1).then(r => r.json()), fetch(url2).then(r => r.json()), ]); for (const result of results) { if (result.status === 'fulfilled') console.log(result.value); else console.log('Failed:', result.reason); } ```

Parallel requests with Promise.all

#
Fetch products and categories simultaneously: ```javascript const BASE_URL = 'https://apilearn.tukas.dev'; async function main() { const [productsData, categories] = await Promise.all([ fetch(`${BASE_URL}/api/products/`).then(r => r.json()), fetch(`${BASE_URL}/api/categories/`).then(r => r.json()), ]); console.log('Total products:', productsData.count); console.log('Categories:', categories.length); } main(); ``` Fetch multiple products by id in parallel: ```javascript async function fetchProduct(id) { return fetch(`${BASE_URL}/api/products/${id}/`).then(r => r.json()); } async function main() { // Fetch products 1-5 simultaneously const products = await Promise.all( [1, 2, 3, 4, 5].map(id => fetchProduct(id)) ); for (const p of products) { console.log(p.name, p.price); } } main(); ``` Load multiple data sources at once for a dashboard: ```javascript async function loadDashboard(token) { const headers = { 'Authorization': `Token ${token}` }; const [productsData, categories, profile, cart] = await Promise.all([ fetch(`${BASE_URL}/api/products/`).then(r => r.json()), fetch(`${BASE_URL}/api/categories/`).then(r => r.json()), fetch(`${BASE_URL}/api/users/profile/`, { headers }).then(r => r.json()), fetch(`${BASE_URL}/api/cart/`, { headers }).then(r => r.json()), ]); console.log(`Welcome ${profile.username}!`); console.log(`${productsData.count} products in ${categories.length} categories`); console.log(`Cart: ${cart.items.length} items`); } ```

Promise.all and parallel fetch reference

#
**Promise.all — basic** ```javascript const [a, b] = await Promise.all([promiseA, promiseB]); // results in same order as input // rejects immediately if any promise rejects ``` **Map pattern for dynamic arrays** ```javascript const ids = [1, 2, 3, 4, 5]; const products = await Promise.all(ids.map(id => fetch(`${BASE_URL}/api/products/${id}/`).then(r => r.json()) )); ``` **Promise.allSettled — partial failures** ```javascript const results = await Promise.allSettled([p1, p2, p3]); const succeeded = results.filter(r => r.status === 'fulfilled').map(r => r.value); const failed = results.filter(r => r.status === 'rejected').map(r => r.reason); ``` **Sequential vs parallel** ```javascript // Sequential — slow const a = await fetchA(); const b = await fetchB(); // waits for A // Parallel — fast const [a, b] = await Promise.all([fetchA(), fetchB()]); ``` **When to use Promise.all** ``` Multiple independent requests → use Promise.all Requests depend on each other → sequential await Any failure should stop everything → Promise.all Handle failures individually → Promise.allSettled ```
01

First Promise.all

#

Use `Promise.all` to fetch `/api/products/` and `/api/categories/` simultaneously. Print the total product count and number of categories.

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

async function main() {
  // fetch products and categories in parallel with Promise.all
}

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

async function main() {
  const [productsData, categories] = await Promise.all([
    fetch(`${BASE_URL}/api/products/`).then(r => r.json()),
    fetch(`${BASE_URL}/api/categories/`).then(r => r.json()),
  ]);
  console.log(productsData.count);
  console.log(categories.length);
}

main();
02

Fetch multiple products in parallel

#

Fetch products with ids 1, 2, 3, 4, 5 all at once using `Promise.all` and `.map()`. Print the name and price of each.

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

async function main() {
  // fetch 5 products in parallel using .map() and Promise.all
}

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

async function main() {
  const products = await Promise.all(
    [1, 2, 3, 4, 5].map(id =>
      fetch(`${BASE_URL}/api/products/${id}/`).then(r => r.json())
    )
  );
  for (const p of products) {
    console.log(p.name, p.price);
  }
}

main();
03

Authenticated parallel requests

#

Get a token, then use `Promise.all` to fetch the profile and the cart simultaneously. Print `username` and cart item count.

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

async function main() {
  const { token } = await fetch(`${BASE_URL}/api/auth/token/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
  }).then(r => r.json());

  const headers = { 'Authorization': `Token ${token}` };

  // fetch profile and cart in parallel
}

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

async function main() {
  const { token } = await fetch(`${BASE_URL}/api/auth/token/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
  }).then(r => r.json());

  const headers = { 'Authorization': `Token ${token}` };

  const [profile, cart] = await Promise.all([
    fetch(`${BASE_URL}/api/users/profile/`, { headers }).then(r => r.json()),
    fetch(`${BASE_URL}/api/cart/`, { headers }).then(r => r.json()),
  ]);

  console.log(profile.username);
  console.log(cart.items.length);
}

main();
04

Compare sequential vs parallel

#

Fetch products with ids 1–5 twice: once sequentially with a loop, once in parallel with `Promise.all`. Measure and print the time for each approach using `Date.now()`.

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

async function main() {
  // sequential
  let start = Date.now();
  // ... loop ...
  console.log('Sequential:', Date.now() - start, 'ms');

  // parallel
  start = Date.now();
  // ... Promise.all ...
  console.log('Parallel:', Date.now() - start, 'ms');
}

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

async function main() {
  // Sequential
  let start = Date.now();
  for (const id of [1, 2, 3, 4, 5]) {
    await fetch(`${BASE_URL}/api/products/${id}/`).then(r => r.json());
  }
  console.log('Sequential:', Date.now() - start, 'ms');

  // Parallel
  start = Date.now();
  await Promise.all(
    [1, 2, 3, 4, 5].map(id =>
      fetch(`${BASE_URL}/api/products/${id}/`).then(r => r.json())
    )
  );
  console.log('Parallel:', Date.now() - start, 'ms');
}

main();
05

Dashboard loader with Promise.all

#

Write a `loadDashboard(token)` function that fetches products, categories, profile, and cart all at once with `Promise.all`. Print a summary: username, product count, category count, cart item count.

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

async function loadDashboard(token) {
  // fetch 4 resources in parallel, print summary
}

async function main() {
  const { token } = await fetch(`${BASE_URL}/api/auth/token/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
  }).then(r => r.json());

  await loadDashboard(token);
}

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

async function loadDashboard(token) {
  const headers = { 'Authorization': `Token ${token}` };

  const [productsData, categories, profile, cart] = await Promise.all([
    fetch(`${BASE_URL}/api/products/`).then(r => r.json()),
    fetch(`${BASE_URL}/api/categories/`).then(r => r.json()),
    fetch(`${BASE_URL}/api/users/profile/`, { headers }).then(r => r.json()),
    fetch(`${BASE_URL}/api/cart/`, { headers }).then(r => r.json()),
  ]);

  console.log(`Welcome, ${profile.username}!`);
  console.log(`${productsData.count} products in ${categories.length} categories`);
  console.log(`Cart: ${cart.items.length} items`);
}

async function main() {
  const { token } = await fetch(`${BASE_URL}/api/auth/token/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username: 'YOUR_USERNAME', password: 'YOUR_PASSWORD' }),
  }).then(r => r.json());

  await loadDashboard(token);
}

main();