Загрузка…
Загрузка…
Waterfall vs Promise.all, stream slow part через Suspense без top-level await, cache() для non-fetch dedupe.
// ❌ Sequential waterfall — tags() waits for posts() waits for user()
export default async function Page() {
const user = await getUser();
const posts = await getPosts(); // could have started already
const tags = await getTags(); // could have started already
return ;
}// ✅ Parallel — independent requests fire together
export default async function Page() {
const [user, posts, tags] = await Promise.all([getUser(), getPosts(), getTags()]);
return ;
}// ✅ Stream the slow part: start the fetch, don't await it here, let Suspense wait
import { Suspense } from 'react';
export default function Page() {
const slow = getSlowReport(); // NOT awaited — kicks off immediately
return (
<>
{/* renders now */}
}>
{/* awaits the promise inside, streams in */}
);
}// Dedupe a non-fetch source (DB/ORM) per request
import { cache } from 'react';
export const getUser = cache(async (id: string) => db.user.find(id));Три паттерна: parallel all, fire-and-stream Suspense, React cache() для ORM — покрывают 90% App Router data fetching.
