Files
nextjs-fetch-data-example/ai/nextjs-style-guide/applied/data-fetch/parallel-server-requests.md

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, можно запустить промис выше и передать его ниже: Передача промиса ниже.