Что сработает раньше: callback или promise
Что проверяют
Знаете ли вы модель выполнения Node: где именно оказывается функция после того, как её передали, и чем очередь микрозадач отличается от фаз цикла событий. Вопрос звучит как загадка, но проверяет способность рассуждать, а не заученный ответ.
Как отвечать
Сначала снимите ложную дихотомию: колбэк и промис это не две очереди, а два стиля API. Колбэк бывает синхронным и выполняется прямо сейчас, до любого промиса.
[1].forEach(() => console.log('sync'));
Promise.resolve().then(() => console.log('micro'));
process.nextTick(() => console.log('tick'));
setTimeout(() => console.log('timer'));
setImmediate(() => console.log('immediate'));Порядок вывода здесь такой: sync, tick, micro, дальше timer и immediate. То есть после синхронного кода Node разбирает очередь nextTick, затем микрозадачи промисов, и только потом переходит к фазам цикла: таймеры, ожидание ввода-вывода, immediate, закрытие дескрипторов.
Отсюда честный ответ: если колбэк асинхронный и приходит из таймера или из ввода-вывода, промис сработает раньше, потому что микрозадачи разбираются между фазами. Если колбэк синхронный, первым будет он.
Где спотыкаются
Отвечают «промис всегда раньше» и не различают синхронный колбэк. Функция, которая иногда зовёт колбэк сразу, а иногда позже, известный источник плавающих багов, поэтому асинхронность в своём API делают безусловной.
Говорят, что микрозадачи выполняются в следующем витке цикла событий. Они выполняются в этом же проходе, сразу после текущего стека и после каждой фазы. Ошибка кажется безобидной, но из неё растут неверные предположения о таймерах.
Забывают про nextTick с приоритетом выше промисов. Рекурсия через него подвешивает процесс: цикл событий не получает управления, и таймеры с сокетами просто не доходят до очереди.