Files
docs/canons/style-guide/applied/data-fetch/parallel-server-requests.md
S.Gromov 86ab6bc8fd feat: добавить хаб документаций
- добавлен React/Vite-лендинг с карточками документаций
- добавлена генерация корневого llms.txt из конфига документов
- добавлена сборка SLM Design через VitePress
- добавлены Dockerfile, Caddyfile и Gitea CI/CD
- настроены контекстные Link headers для llms.txt
2026-05-13 10:12:31 +03:00

3.3 KiB
Raw Blame History

title, description, keywords
title description keywords
Параллельные серверные запросы Как запускать независимые REST-запросы на сервере без waterfall.
rest
promise.all
параллельные запросы
server components

Параллельные серверные запросы

Если серверному компоненту нужно несколько независимых данных, запускайте запросы до ожидания результата. Последовательный await создаёт waterfall и замедляет рендер.

Когда использовать

  • Запросы независимы друг от друга.
  • Все данные нужны текущему серверному компоненту перед возвратом UI.
  • Нельзя или не нужно стримить часть UI отдельно.

Хорошо

import { petStoreApi, StatusEnum } from 'infra/pet-store-api'
import { PetsDashboardScreen } from 'screens/pets-dashboard'

export default async function PetsDashboardPage() {
  const availablePetsPromise = petStoreApi.pet.findPetsByStatus({
    status: StatusEnum.Available,
  })
  const pendingPetsPromise = petStoreApi.pet.findPetsByStatus({
    status: StatusEnum.Pending,
  })
  const soldPetsPromise = petStoreApi.pet.findPetsByStatus({
    status: StatusEnum.Sold,
  })

  const [availablePets, pendingPets, soldPets] = await Promise.all([
    availablePetsPromise,
    pendingPetsPromise,
    soldPetsPromise,
  ])

  return (
    <PetsDashboardScreen
      availablePets={availablePets}
      pendingPets={pendingPets}
      soldPets={soldPets}
    />
  )
}

Плохо

export default async function PetsDashboardPage() {
  const availablePets = await petStoreApi.pet.findPetsByStatus({
    status: StatusEnum.Available,
  })
  const pendingPets = await petStoreApi.pet.findPetsByStatus({
    status: StatusEnum.Pending,
  })
  const soldPets = await petStoreApi.pet.findPetsByStatus({
    status: StatusEnum.Sold,
  })

  return (
    <PetsDashboardScreen
      availablePets={availablePets}
      pendingPets={pendingPets}
      soldPets={soldPets}
    />
  )
}

Во втором примере каждый следующий запрос ждёт предыдущий, хотя они независимы.

Зависимые запросы

Если второй запрос зависит от результата первого, последовательный await допустим:

export default async function OrderPage({ params }: OrderPageProps) {
  const { id } = await params
  const order = await petStoreApi.store.getOrderById({ orderId: Number(id) })
  const pet = await petStoreApi.pet.getPetById({ petId: order.petId })

  return <OrderScreen order={order} pet={pet} />
}

Не превращайте зависимый сценарий в Promise.all искусственно.

Когда выбрать другую стратегию

Если часть данных не обязательна для первого блока UI, можно запустить промис выше и передать его ниже: Передача промиса ниже.