[Promise.reject(42), Promise.resolve(4)].forEach((item, i) => {
Promise.resolve(item)
.then(() => console.info("resolve", i))
.catch(() => console.info("reject", i));
});Ожидаемый результат:
reject 0
resolve 1
Фактический результат:
resolve 1
reject 0
Почему вы ожидаете, что обработчик отклонения запустится первым? Почему вы вообще ожидаете определенного заказа, если у вас есть две независимые цепочки обещаний?
Эти вымышленные примеры с немедленным разрешением/отклонением обещаний на самом деле не имеют отношения к реальному программированию обещаний, где разрешение/отклонение происходит в неопределенное время в будущем. Как сказал Берги, у вас есть две отдельные цепочки обещаний, которые полностью независимы друг от друга. При любом использовании обещаний в реальном мире эти две цепочки будут работать независимо, в свое собственное время и не иметь никакого отношения друг к другу.
Существуют независимые цепочки обещаний, но в выводе должна быть некоторая логика, поскольку они используют одну и ту же очередь заданий. Ответ Николая правильный.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Каждый вызов .then или .catch создает новое обещание, которое зависит от предыдущего обещания. Итак, ваш код строит две цепочки обещаний. Причина такого поведения заключается в том, что журналы находятся в разных местах цепочки. Журнал случая отклонения находится на один уровень глубже в цепочке, чем журнал случая разрешения.
Очередь микрозадач определяет, какой обратный вызов будет выполняться следующим, и поскольку оба промиса верхнего уровня запускаются в установленном состоянии, в очереди будет две записи. Как только первый обратный вызов завершится, промис ниже него может разрешиться и поставить себя в очередь, но ему придется идти за обещанием, которое уже находится в очереди из другого стека. Другими словами, разрешение промисов будет идти зигзагом между двумя стеками: ignore1 ->solve1 -> ignore2 ->solve2 -> ignore3 ->solve3 (жирным шрифтом выделены журналы).
Таким образом, он может сначала просматривать отклоненный стек на каждом уровне, но ему придется копнуть глубже, прежде чем он дойдет до .catch, в котором есть console.info.
Если вы внесли следующее изменение, оно будет работать так, как вы ожидаете (.then принимает второй параметр для обработки случая catch):
[Promise.reject(42), Promise.resolve(4)].forEach((item, i) => {
Promise.resolve(item)
.then(
() => console.info("resolve", i),
() => console.info("reject", i)
)
});[Promise.reject(42), Promise.resolve(4)].forEach((item, i) => {
try {Promise.resolve(item)
.then(() => console.info("resolve", i))}
finally {
Promise.resolve(item)
.catch(() => console.info("reject", i))}
}
);
Я написал пример, используя, наконец, вместо .catch, чтобы определить, когда сообщение регистрируется. Я думаю, это как-то связано с иерархией компиляции.
Это никогда не регистрируется reject