Передаёшь AbortSignal в Worker через postMessage и ждёшь abort как гарантию отмены? Типичная ловушка: сигнал с таймаутом стартует в момент создания, а не когда Worker его получает. Результат — Worker грузится дольше таймаута и получает уже aborted: true, не выполнив ни строчки кода.
Таймаут живёт в main thread, Worker получает мёртвую копию
const controller = new AbortController();
const timeoutSignal = AbortSignal.timeout(5000);
const combined = AbortSignal.any([controller.signal, timeoutSignal]);
worker.postMessage({ type: 'start', signal: combined });
Таймер из
AbortSignal.timeout() не Transferable. Сигнал передаётся как структурированная копия состояния, но оригинал остаётся в main thread. Если таймаут срабатывает после передачи — Worker никогда не узнает об этом. Memory leak гарантирован, так как замыкание с обработчиком abort не очищается.Нельзя сбросить сработавший сигнал
Когда
AbortSignal.timeout() abort'нул внешний сигнал через AbortSignal.any(), контроллер становится мёртвым навсегда:controller.signal.addEventListener('abort', () => console.log('aborted'));
timeoutSignal.dispatchEvent(new Event('abort'));
controller.abort(); // 0 реакций, контроллер уже не активенЭто race condition, который не ловится без логов: ты пытаешься вызвать
controller.abort() позже, но сигнал уже в состоянии aborted: true от таймаута.Практический совет для Workers
Создавай
AbortSignal.timeout() прямо внутри Worker, а не передавай снаружи:// Внутри Worker
self.onmessage = ({ data }) => {
const timeout = AbortSignal.timeout(5000);
if (data.signal.aborted) return;
timeout.addEventListener('abort', () => controller.abort());
};
Перед стартом работы явно проверяй
if (signal.aborted) return. Используй один центральный AbortController для всех вложенных сигналов вместо цепочек через AbortSignal.any(). Это снижает риск невидимых race condition при комбинировании таймаутов.Вывод: AbortSignal.timeout() хорош для простых таймеров в одном потоке, но при передаче в Workers и комбинировании сигналов требует явной проверки состояния и изоляции создания таймаута внутри получателя.