Асинхронные задачи
Это практический слой асинхронности: не «что такое промис», а «построй из промисов рабочий инструмент». Такие задачи на собеседовании ценятся тем, что за короткий код видно всю модель исполнения — понимаете ли вы, что промис разрешается один раз, что .then планирует микрозадачу, что setTimeout и setInterval ведут себя по-разному под медленной сетью.
Каждый слой ниже — это отдельный приём, который стоит уметь написать по памяти и объяснить построчно. Мы разбираем механизм, а не заученный ответ: как обёртка сохраняет this, зачем счётчик оставшихся, почему хвост-промис глотает ошибки, чем отмена лучше сравнения термов. Порядок слоёв — от фундамента (обернуть колбэк) к боевым паттернам (отмена, сериализация).
Карта темы
- Колбэк в промис — обёртка
promisify, сохранениеthisи соглашения error-first. - Реализация комбинаторов —
Promise.all/anyс нуля через счётчик, массив по индексу иAggregateError. - Внутренности промиса — конечный автомат состояний, очереди колбэков и как
.thenпланирует микрозадачу. - EventEmitter —
on/off/emitнаMapизSet, изоляция ошибок и цепочка черезthis. - Fetch с повторами — ограниченный ретрай с задержкой и промис-обёрткой над
setTimeout. - Поллинг-клиент — самоперепланируемый
setTimeoutпротивsetIntervalи очистка буфера лишь при успехе. - AbortController — отмена устаревшего запроса в полёте и лечение гонки порядка ответов.
- Сериализация записей — хвост-промис, гарантирующий очередь без конкуренции и с изоляцией ошибок.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Обёртка promisify как стрелочная функция | Теряется this точки вызова |
push результатов вместо записи по индексу | Порядок массива путается при завершении вразнобой |
setInterval для опроса под медленной сетью | Запросы наслаиваются друг на друга |
| Перепланировать до завершения запроса | Возвращается перекрытие, которое и хотели убрать |
Продвигать хвост очереди без .catch | Одно отклонение ломает всю дальнейшую очередь |
| Игнорировать гонку запросов автоподсказок | Медленный старый ответ затирает более новый |
| Очищать буфер до успешной отправки | Неудачный POST молча теряет события |
Значение для собеседований
Это формат «напиши функцию у доски». Интервьюер даёт заготовку сигнатуры и просит реализацию, а затем давит уточнениями: «а если вход пустой?», «а если запрос медленнее интервала?», «почему обычная функция, а не стрелка?». Ответы на них и отделяют понимание механизма от заученного шаблона.
Что обычно проверяют:
- Как обернуть error-first колбэк в промис, сохранив
thisи аргументы. - Как реализовать комбинатор с сохранением порядка и корректной обработкой пустого входа.
- Почему
setTimeout-самоперепланирование безопаснееsetIntervalпод медленной сетью. - Как
AbortControllerотменяет запрос и лечит гонку порядка ответов. - Как хвост-промис сериализует записи и почему он должен глотать ошибки.
Типичный неверный ответ: «await fetch(...) в цикле и так идёт параллельно» или «setInterval надёжнее держит свежесть». Оба выдают непонимание того, что await в цикле сериализует шаги, а setInterval стреляет по часам независимо от того, завершился ли прошлый запрос.