So‘rovlar sharsharasi: ketma-ket await sahifani qanday sekinlashtiradi
Server komponentlarda ketma-ket await nima uchun sahifani sekinlashtiradi va uni Promise.all hamda Suspense bilan qanday tuzatish mumkin.
Sahifa sekin ochilyapti, lekin har bir so‘rov alohida tez ishlaydi. Ko‘pincha sabab so‘rovlarning o‘zida emas, ularning tartibida bo‘ladi: ular bir-birini kutib turadi. Bunga request waterfall, ya’ni so‘rovlar sharsharasi deyiladi.
Muammo qanday ko‘rinadi
export default async function Dashboard() {
const user = await getUser(); // 300 ms
const orders = await getOrders(); // 400 ms
const stats = await getStats(); // 500 ms
return <DashboardView user={user} orders={orders} stats={stats} />;
}Kod toza va o‘qilishi oson. Lekin har bir await keyingi qatorni to‘xtatib turadi,
shuning uchun sahifa 1200 ms kutadi. Bu uch so‘rov bir-biriga bog‘liq emas, demak
ularni birga boshlash mumkin edi.
Birinchi yechim: Promise.all
export default async function Dashboard() {
const [user, orders, stats] = await Promise.all([
getUser(),
getOrders(),
getStats(),
]);
return <DashboardView user={user} orders={orders} stats={stats} />;
}Endi uchala so‘rov bir vaqtda ketadi va sahifa eng sekinini, ya’ni 500 ms kutadi.
Ikki narsani yodda tuting. Bittasi xato bersa, Promise.all butunlay rad etiladi;
qisman natija kerak bo‘lsa, Promise.allSettled ishlating. Ikkinchisi: foydalanuvchi
baribir eng sekin so‘rov tugamaguncha hech narsa ko‘rmaydi.
Ikkinchi yechim: Suspense bilan bo‘laklash
Har bir bo‘lak o‘z ma’lumotini o‘zi olsa, ular parallel ishlaydi va tayyor bo‘lgani darhol ekranga chiqadi:
import { Suspense } from "react";
export default function Dashboard() {
return (
<>
<Suspense fallback={<HeaderSkeleton />}>
<UserHeader />
</Suspense>
<Suspense fallback={<OrdersSkeleton />}>
<Orders />
</Suspense>
<Suspense fallback={<StatsSkeleton />}>
<Stats />
</Suspense>
</>
);
}
async function Orders() {
const orders = await getOrders();
return <OrderList orders={orders} />;
}Sarlavha 300 ms da, buyurtmalar 400 ms da, statistika 500 ms da ko‘rinadi. Umumiy vaqt o‘zgarmadi, lekin foydalanuvchi bo‘sh ekranga qarab o‘tirmaydi.
So‘rovlar haqiqatan bog‘liq bo‘lsa
Ba’zan ketma-ketlik zarur: buyurtmalarni olish uchun avval foydalanuvchi ID’si kerak. Bunday holda bog‘liq bo‘lmaganlarini oldinroq boshlab qo‘ying:
const statsPromise = getStats(); // boshlandi, lekin kutilmayapti
const user = await getUser();
const orders = await getOrders(user.id);
const stats = await statsPromise;Bir xil ma’lumot bir nechta komponentga kerak bo‘lsa, funksiyani React’ning cache
funksiyasi bilan o‘rang. Shunda bitta render davomida so‘rov faqat bir marta ketadi:
import { cache } from "react";
export const getUser = cache(async () => {
return db.user.current();
});Qanday topish mumkin
- Bitta funksiyada ketma-ket kelgan bir nechta
awaitni qidiring va har biri oldingisining natijasiga muhtojmi, tekshiring. - Ota komponent
awaitqilib, keyin bola komponent hamawaitqilsa, bu ham sharshara: bola ota tugamaguncha boshlanmaydi. - Har bir so‘rov vaqtini log qiling. Yig‘indi sahifa vaqtiga teng bo‘lsa, ular ketma-ket ishlayapti.
Xulosa
So‘rovni tezlashtirish qiyin, tartibini o‘zgartirish esa oson. Avval bog‘liq bo‘lmagan so‘rovlarni parallel qiling, keyin sekin bo‘laklarni Suspense ortiga oling. Ko‘p hollarda shuning o‘zi sahifani bir necha barobar tez his qildiradi.