Функція requestIdleCallback()
requestIdleCallback(callback, [options]) реєструє колбек, який виконається тоді, коли браузер не зайнятий відмальовуванням чи обробкою подій, тобто у простої («idle time»). Це спосіб робити фонову роботу, не крадучи час у рендера й не підвішуючи інтерфейс.
Теорія
TL;DR
requestIdleCallback(fn)ставитьfnу чергу idle-колбеків з найнижчим пріоритетом.- Колбек отримує об'єкт
deadlineзtimeRemaining()іdidTimeout. - Викликається у «вікні простою» між кадрами, коли рендер і мікротаски вже завершені.
{ timeout: N }гарантує виклик не пізніше ніж через N мс, навіть якщо простою не було.- Повертає числовий ID, скасовується через
cancelIdleCallback(id). - Не для критичних задач: на навантаженій або прихованій вкладці виклик може відкластися надовго.
Швидкий приклад
requestIdleCallback((deadline) => {
while (deadline.timeRemaining() > 0) {
console.log('Doing a background task');
}
console.log('The browser is busy again, waiting for the next idle window');
});Тут:
deadline, це спеціальний об'єкт, який передається в колбек;deadline.timeRemaining()показує, скільки мілісекунд лишилося «вільними» до наступного кадру;- ви робите роботу, поки є час, а якщо не встигли, браузер викличе колбек знову в наступному вікні простою.
Що таке простій і як працює виклик
Браузер малює кадри приблизно 60 разів на секунду, тобто кожні 16.6 мс. Якщо якийсь кадр зайняв лише, скажімо, 10 мс, у браузера залишається приблизно 6 мс вільного часу, і саме туди може потрапити ваш requestIdleCallback. Так виконуються незначні або фонові задачі, некритичні до часу, без гальмування інтерфейсу.
Крок за кроком:
- Ви викликаєте
requestIdleCallback(fn). - Браузер додає
fnу чергу задач idle callbacks. - Коли Event Loop, відмальовування й мікротаски завершені, а до наступного кадру ще є час, браузер викликає ваш колбек.
- Якщо вкладка неактивна або вільного часу немає, колбек може відкладатися.
Аргументи: deadline і timeout
requestIdleCallback(callback, { timeout: 2000 });callback(deadline), функція, яка отримає об'єкт:deadline.timeRemaining(), скільки мілісекунд лишилося «до зайнятості»;deadline.didTimeout,true, якщо вичерпався таймаут і колбек викликали «примусово».
options.timeout, максимальний час очікування. Якщо вільного моменту так і не з'явилося, колбек усе одно виконається через задану кількість мілісекунд.
Перевірка didTimeout дає змогу розрізнити два режими: у справжньому простої можна спокійно працювати, поки timeRemaining() > 0, а при вимушеному виклику timeRemaining() зазвичай дорівнює нулю, і варто зробити лише мінімум найнеобхіднішого.
Розбиття важкої роботи на частини
const tasks = Array.from({ length: 10000 }, (_, i) => i);
function processTasks(deadline) {
while (deadline.timeRemaining() > 0 && tasks.length > 0) {
const task = tasks.shift();
// do a portion of the work
console.log('Task processed', task);
}
if (tasks.length > 0) {
requestIdleCallback(processTasks);
}
}
requestIdleCallback(processTasks);Такий підхід дозволяє обробити тисячі елементів без лагів: UI лишається чутливим, бо робота виконується в паузах між кадрами. Ключова деталь, це повторна реєстрація колбека, доки черга не спорожніє: одного виклику майже ніколи не вистачає.
Порівняння з setTimeout і requestAnimationFrame
| Критерій | setTimeout | requestAnimationFrame | requestIdleCallback |
|---|---|---|---|
| Мета | Виконати через N мс | Виконати перед перемальовуванням кадру | Виконати в паузі між кадрами |
| Пріоритет | Середній | Високий (для анімацій) | Низький (фонові задачі) |
| Залежить від навантаження | Ні | Так, синхронізується з кадром | Так, викликається лише коли браузер вільний |
| При неактивній вкладці | Може тротлитися | Призупиняється | Може затриматися надовго |
| Використання | Таймери, затримки | Анімації, плавні оновлення | Легкі фонові обчислення, кеш, логіка довантаження |
Підтримка браузерами і фолбек
requestIdleCallback є не в усіх браузерах, зокрема його немає в Safari, тому краще мати фолбек:
const ric = window.requestIdleCallback || function (cb) {
return setTimeout(() => cb({ timeRemaining: () => 0, didTimeout: true }), 1);
};Його не можна використовувати для критичних задач, бо він може не викликатися довго, якщо вкладка навантажена.
Підсумок:
| Властивість | Значення |
|---|---|
| Що робить | Викликає колбек, коли в браузера є вільний час |
| Передає об'єкт | deadline з timeRemaining() і didTimeout |
| Коли виконується | У вікнах простою між кадрами |
| Використовується для | Фонових задач, кешування, довантаження даних |
| Скасовується через | cancelIdleCallback(id) |
| Повертає | Числовий ID, як у таймерів |
Типові помилки
- Покладатися на нього для критичної логіки. Колбек може не виконатися хвилинами, якщо сторінка постійно зайнята. Для гарантії ставте
timeout. - Ігнорувати
timeRemaining(). Цикл без перевірки залишку часу з'їдає кадр і повертає ті самі лаги, від яких ви тікали. - Не перереєстровувати колбек. Одне вікно простою рідко вміщає всю роботу, тому в кінці треба знову викликати
requestIdleCallback, якщо черга не порожня. - Малювати з нього. Зміни DOM усередині idle-колбека відбуваються після кадру і спричиняють зайвий reflow. Для візуальних оновлень є
requestAnimationFrame. - Забувати про відсутність підтримки. Без фолбека код просто нічого не робить у Safari, і баг довго лишається непоміченим.
- Не скасовувати запланований колбек. Після зникнення компонента виклик лишається в черзі, тому потрібен
cancelIdleCallback(id).
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.