Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Черга задач (task queue)». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Черга задач (task queue) це структура даних, у якій зберігаються колбеки, що чекають на виконання після звільнення стека викликів.** Це ключовий елемент механізму Event Loop: поки рушій зайнятий функціями у стеку, колбеки від `setTimeout`, `setInterval` і подій DOM чекають своєї черги. Коли стек порожніє, Event Loop бере першу задачу з черги і кладе її у стек. Важливо, що спочатку повністю спорожняється черга мікрозадач (`Promise.then`, `queueMicrotask`), і лише потім береться наступна макрозадача. ```javascript console.log('1'); setTimeout(() => console.log('2'), 0); // у чергу задач console.log('3'); // 1, 3, 2 ``` **Ключове:** порядок такий: спочатку стек, потім усі мікрозадачі, і тільки потім одна задача з черги задач.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Черга задач (Task Queue) це структура даних, у якій зберігаються задачі (колбеки), що очікують на виконання після звільнення стека викликів (Call Stack).** Вона є ключовим елементом механізму Event Loop (циклу подій) у JavaScript. ## Теорія ### TL;DR - Черга задач зберігає колбеки, які вже готові виконатися, але чекають, доки звільниться стек викликів. - JavaScript однопотоковий, тому одночасно виконується лише одна задача. - Event Loop бере першу задачу з черги (FIFO) і кладе її у стек, щойно стек стає порожнім. - Черг насправді дві: черга макрозадач (`setTimeout`, події DOM) і черга мікрозадач (`Promise.then`, `queueMicrotask`). - Мікрозадачі завжди виконуються раніше за наступну макрозадачу. - Порядок такий: стек, потім мікрозадачі, потім макрозадачі. ### Швидкий приклад ```javascript console.log('1'); setTimeout(() => { console.log('2'); }, 0); console.log('3'); ``` Вивід у консолі: ```text 1 3 2 ``` ### Ключова ідея JavaScript це **однопотокова мова**, вона може виконувати **лише одну задачу за раз**. Коли рушій зайнятий виконанням функцій у **стеку викликів**, решта задач, наприклад обробники кліків, `setTimeout`, мережеві колбеки і таке інше, чекають своєї черги у **черзі задач (task queue)**. Коли стек викликів стає порожнім, **Event Loop** бере першу задачу з черги і поміщає її у стек. І так по колу, нескінченно. ### Покроковий розбір прикладу 1. `console.log('1')` виконується одразу і друкує `1`. 2. `setTimeout(...)`: браузер ставить таймер. Після спрацювання таймера колбек потрапляє **у чергу задач**, а не виконується миттєво. 3. `console.log('3')` виконується і друкує `3`. 4. Коли **стек викликів порожній**, **Event Loop** бере задачу з черги (колбек із `setTimeout`) і поміщає її у стек, що друкує `2`. Саме тому нульова затримка в `setTimeout` означає «якнайшвидше після звільнення стека», а не «негайно». ### Черга задач проти черги мікрозадач У JavaScript є **дві черги**: | Тип черги | Джерело задач | Коли виконуються | | --- | --- | --- | | **Task Queue (macro tasks)** | `setTimeout`, `setInterval`, події DOM, колбеки введення/виведення і таке інше | Після очищення стека і всіх мікрозадач | | **Microtask Queue** | `Promise.then`, `queueMicrotask`, `MutationObserver` | Одразу після поточної задачі, **до** наступної макрозадачі | Різниця принципова: черга мікрозадач вичерпується повністю, а з черги макрозадач за один оберт циклу береться лише одна задача. ### Приклад з мікрозадачами ```javascript console.log('A'); setTimeout(() => console.log('B'), 0); Promise.resolve().then(() => console.log('C')); console.log('D'); ``` Порядок виводу: ```text A D C B ``` Пояснення: - `A`, `D` виконуються одразу, це синхронний код у стеку викликів. - `C` це мікрозадача, вона виконується одразу після очищення стека. - `B` це макрозадача, вона виконується після всіх мікрозадач. ### Коротко про терміни | Термін | Опис | | --- | --- | | **Task Queue** | Черга макрозадач, зберігає колбеки від `setTimeout`, подій і таке інше | | **Microtask Queue** | Черга мікрозадач, для `Promise.then`, `queueMicrotask` | | **Event Loop** | Механізм, що стежить за стеком і чергами та вирішує, що виконувати далі | | **Порядок** | Спочатку стек, потім мікрозадачі, потім макрозадачі | ### Типові помилки - **Вважати, що `setTimeout(fn, 0)` виконає `fn` негайно.** Колбек лише стає в чергу задач і чекає, доки стек спорожніє. - **Плутати чергу задач зі стеком викликів.** Стек це LIFO і те, що виконується зараз; черга це FIFO і те, що виконуватиметься потім. - **Ставити промиси і таймери в один ряд.** `Promise.then` іде в чергу мікрозадач і завжди випередить будь-який `setTimeout`, навіть з нульовою затримкою. - **Нескінченно породжувати мікрозадачі.** Якщо мікрозадача щоразу додає нову мікрозадачу, черга ніколи не спорожніє і макрозадачі та рендеринг просто не отримають керування. - **Думати, що черга робить код паралельним.** Усе одно виконання проходить через один потік і один стек, просто в іншому порядку.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.