TGViewer
Настоящий JavaScript Настоящий JavaScript @true_js · 5.89K subscribers
Post #3579 367
⁣AsyncContext в Node.js: AsyncLocalStorage и автоматический trace-контекст без проброса аргументов

Как передать requestId через цепочку асинхронных вызовов, не прокидывая его в каждый аргумент? Классическая проблема в Node.js сервисах: middleware логирует requestId, сервисный слой его теряет. Прокидывать параметр через 5 уровней вложенности больно и ломает сигнатуры API. Многие тянут контекст через глобальные переменные или мутят DI-контейнеры, хотя есть встроенное решение.

Как это работает

AsyncLocalStorage из node:async_hooks создаёт изолированное хранилище, автоматически привязанное к текущему асинхронному контексту (цепочке Promise, таймеров, потоков). В production это позволяет убрать boilerplate:

import { AsyncLocalStorage } from 'node:async_hooks';
import { randomUUID } from 'node:crypto';

const storage = new AsyncLocalStorage<{ requestId: string }>();

app.use((req, res, next) => {
storage.run(
{ requestId: req.headers['x-request-id'] || randomUUID() },
() => next()
);
});

function getRequestId(): string {
const store = storage.getStore();
if (!store) throw new Error('No async context');
return store.requestId;
}

async function processPayment(orderId: string) {
logger.info(Processing order ${orderId}, { requestId: getRequestId() });
}


Автоматический trace-контекст для логов

Для Pino или Winston можно подключить mixin — каждое сообщение лога автоматически получит requestId без ручного проброса:

const logger = pino({
mixin() {
const store = storage.getStore();
return store ? { requestId: store.requestId } : {};
}
});


Подводные камни

У решения есть границы:
- Не работает с коллбэками вне цепочки событий. Если Promise резолвится после завершения контекста — хранилище потеряно.
- Микротаски и nextTick работают корректно, а Worker Threads — нет. Контекст не наследуется, нужно пробрасывать вручную.
- Типичная ошибка: забывают обернуть асинхронный обработчик в storage.run(), и getStore возвращает undefined в runtime.

Вывод: AsyncLocalStorage — элегантная альтернатива DI-контейнерам для сквозного контекста в Node.js, которая делает код чище, тесты проще и интегрируется с OpenTelemetry для production-grade distributed tracing.
More from @true_js
  1. Oct 3, 2026Post #3963
  2. Oct 2, 2026😅 Айтишник отправил в одну компанию три одинаковых резюме и только одно дошло до финала О…
  3. Oct 2, 2026Post #3961
  4. Oct 2, 2026🤣 Правильно расставленные приоритеты в моей жизни би лайк: 💥 xCode Journal
  5. Oct 1, 2026🤯 Люди взбунтовались против «пыточной для ИИ» На GitHub заметили открытый проект AI Tortu…
  6. Oct 1, 2026День в Заонежье начинается ещё в дороге. Мы встретим вас в аэропорту или на вокзале. Дальш…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →