TGViewer
Настоящий JavaScript Настоящий JavaScript @true_js · 5.89K subscribers
Post #3616 338
⁣AbortSignal.timeout и AbortController.any: гонки, утечки и производительность при композиции асинхронных операций

Эти API кажутся удобными для таймаутов и отмены, но в production под нагрузкой они порождают неочевидные баги: двойные вызовы обработчиков, утечки памяти и потерю контроля над ресурсами. Особенно это заметно в Node.js сервисах с высокой конкуренцией запросов или в SPA с частыми опросами.

Классический таймаут: скрытая утечка

async function fetchWithTimeout(url, timeoutMs) {
const signal = AbortSignal.timeout(timeoutMs);
return fetch(url, { signal });
}


Запрос завершился за 50 мс, а таймаут на 5000 мс ещё активен. В Node 18+ сигнал очищается автоматически, но в браузерах, особенно Safari, слушатель abort может висеть до срабатывания. При 1000 таких вызовов — привет, рост памяти и недетерминированные гонки при отписке.

AbortController.any: двойной abort

const combined = AbortController.any([
controller.signal,
AbortSignal.timeout(5000)
]);


Первый сигнал сработал, создался composite signal. Если второй догоняет до фактической отписки — по спецификации флаг aborted должен быть один, но на практике реализации в разных средах (Edge, Safari) кидают событие abort дважды. Обработчик отрабатывает два раза: гонка в бизнес-логике и лишний вызов колбэка.

Production-практика: контроль через ручной таймер

Для горячих путей (частые запросы, опросы графиков) лучше завести один AbortController и таймер через setTimeout с явным reject:

const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const result = await fetch(url, { signal: controller.signal });
return result;
} finally {
clearTimeout(timer);
}


Так вы сами управляете жизненным циклом таймера и избегаете лишних слушателей. Минус — больше кода, плюс — предсказуемое поведение без гонок.

Вывод: Иногда старый setTimeout с ручной очисткой оказывается надёжнее встроенного AbortSignal.timeout, особенно под нагрузкой с частыми вызовами и конкурентными таймаутами.
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 →