Skip to content

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

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

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

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

Хорошо

tsx
import { petStoreApi } from 'infrastructure/pet-store-api'
import { PetsDashboardScreen } from 'screens/pets-dashboard'

export default async function PetsDashboardPage() {
  const availablePetsPromise = petStoreApi.pet.findPetsByStatus({ status: 'available' })
  const pendingPetsPromise = petStoreApi.pet.findPetsByStatus({ status: 'pending' })
  const soldPetsPromise = petStoreApi.pet.findPetsByStatus({ status: 'sold' })

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

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

Плохо

tsx
export default async function PetsDashboardPage() {
  const availablePets = await petStoreApi.pet.findPetsByStatus({ status: 'available' })
  const pendingPets = await petStoreApi.pet.findPetsByStatus({ status: 'pending' })
  const soldPets = await petStoreApi.pet.findPetsByStatus({ status: 'sold' })

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

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

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

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

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

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

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

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

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