Your loop yields every 500 items. It still freezes. Here's why (and a fix)
Описание и применение
В цикле, который обрабатывает массив, частое ожидание каждые 500 элементов не всегда предотвращает зависание, если несколько тяжёлых элементов находятся рядом. Решение – «time‑sliced»: ожидать по времени, а не по количеству, что сохраняет отзывчивость и не увеличивает общее время выполнения.
Задача
Long loops that yield every N items can still freeze the event loop when a cluster of heavy items appears, causing timers to fire late and requests to time out.
Результат
time‑sliced achieves similar total runtime to a plain loop while keeping the longest event‑loop freeze down to 11 ms (vs 254 ms with every‑500 strategy) and remaining responsive during large imports.
Рабочий процесс
- Process rows one by one
- Measure elapsed time since last yield
- If elapsed time exceeds budget, await yieldToEventLoop() (setImmediate or setTimeout(0) depending on runtime)
- Reset budget timer and continue processing
Доказательства
When items are cheap, you yield rarely, so overhead stays low. When items are slow, you yield often, so nothing freezes.
time‑sliced finishes in about the same time as the plain loop, and the event loop never freezes much longer than the budget.
A 1 ms heartbeat timer measures the longest event-loop freeze. Median of 3 runs, Node.js 24.
- Дата записи: 2026-10-26T05:11:21.189Z