🔴 CRITICAL Impact (2–10× улучшение)
Promise.all() для независимых операций
Самое базовое и важное правило — параллелизация независимых операций
❌ Неправильно (3 round trips):
const user = await fetchUser()
const posts = await fetchPosts()
const comments = await fetchComments()
✅ Правильно (1 round trip):
const [user, posts, comments] = await Promise.all([
fetchUser(),
fetchPosts(),
fetchComments()
])
Мои мысли: Логичное уменьшение критического пути за счёт параллельного старта всего, что не зависит друг от друга. Важно помнить: правило применимо только к независимым запросам. Если при падении одного запроса вы всё равно можете продолжать работу — используйте
Promise.allSettled().---
Не допускайте waterfall-цепочек в API routes
Критично для серверного кода — запускайте независимые операции сразу
❌ Неправильно (config ждёт auth, data ждёт обоих):
export async function GET(request: Request) {
const session = await auth()
const config = await fetchConfig()
const data = await fetchData(session.user.id)
return Response.json({ data, config })
}
✅ Правильно (auth и config стартуют одновременно):
export async function GET(request: Request) {
const sessionPromise = auth()
const configPromise = fetchConfig()
const session = await sessionPromise
const [config, data] = await Promise.all([
configPromise,
fetchData(session.user.id)
])
return Response.json({ data, config })
}
Мои мысли: В серверных хендлерах waterfall особенно дорогой, поэтому здесь критично отслеживать такие цепочки. Обязательно следите за неймингом промисов: в подобных кейсах код легко превращается в кашу, и поддерживать его становится сложно.
---
Dependency-based parallelization
Продвинутая параллелизация — максимизация параллелизма при частичных зависимостях
❌ Неправильно (profile ждёт config без причины):
const [user, config] = await Promise.all([
fetchUser(),
fetchConfig()
])
const profile = await fetchProfile(user.id)
✅ Правильно с better-all (config и profile параллельно):
import { all } from 'better-all'
const { user, config, profile } = await all({
async user() { return fetchUser() },
async config() { return fetchConfig() },
async profile() {
return fetchProfile((await this.$.user).id)
}
})
✅ Альтернатива без библиотеки:
const userPromise = fetchUser()
const profilePromise = userPromise.then(user => fetchProfile(user.id))
const [user, config, profile] = await Promise.all([
userPromise,
fetchConfig(),
profilePromise
])
Мои мысли: Мне ближе вариант без библиотеки — минимум магии и максимум профита. Библиотека может повышать «выразительность», но, как по мне, читаемость часто становится хуже.