Как работает очередь
Что проверяют
Знаете ли вы принцип FIFO и умеете ли реализовать очередь в JavaScript без скрытой линейной стоимости операций. Во фронтенде вопрос почти всегда уходит в event loop: чем очередь задач отличается от очереди микрозадач.
Как отвечать
Очередь это структура «первым пришёл, первым вышел»: добавляют в хвост (enqueue), забирают из головы (dequeue). Обе операции должны работать за O(1).
Встроенной очереди в JavaScript нет, и тут первый подвох:
- массив с
pushиshift: самый короткий вариант, ноshiftпо спецификации сдвигает все оставшиеся индексы, в общем случае это O(n). На десятке элементов неважно, на сотнях тысяч заметно; - указатель головы: храните индекс
head, приdequeueвозвращайтеitems[head++]и время от времени отрезайте прочитанную часть. Это O(1) почти без лишнего кода; - связный список: узлы со ссылкой
nextи указатели на голову и хвост; - два стека:
pushв первый, а когда второй пуст, всё перекладывают туда и берут с конца. Амортизированно O(1), частая задача на собеседовании.
Где очередь встречается во фронтенде:
- event loop: колбэки
setTimeoutи событий ждут в очереди задач, колбэки промисов иqueueMicrotaskв очереди микрозадач. После каждой задачи движок выполняет все микрозадачи и только потом может перерисовать страницу; - ограничение параллельных запросов: сотня загрузок по три одновременно, остальные ждут в очереди;
- обход в ширину (BFS): обход DOM-дерева или вложенного меню по уровням;
- отложенные действия: отправка аналитики пачками, повтор запросов после восстановления сети.
Если элементам нужен приоритет, это уже приоритетная очередь, её строят на двоичной куче, а не на отсортированном массиве.
Где спотыкаются
Используют shift в горячем цикле обхода и получают O(n²) на большом дереве.
Путают очередь со стеком и в BFS берут элемент с конца, превращая обход в поиск в глубину.
Считают, что setTimeout(fn, 0) выполнится раньше Promise.resolve().then(fn). Микрозадачи всегда выполняются до следующей задачи.