Почему следующий код сначала разрешает, а не отклоняет?

[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
stackoverflow.com/a/59761869
VLAZ 18.06.2024 21:19

Почему вы ожидаете, что обработчик отклонения запустится первым? Почему вы вообще ожидаете определенного заказа, если у вас есть две независимые цепочки обещаний?

Bergi 18.06.2024 22:37

Эти вымышленные примеры с немедленным разрешением/отклонением обещаний на самом деле не имеют отношения к реальному программированию обещаний, где разрешение/отклонение происходит в неопределенное время в будущем. Как сказал Берги, у вас есть две отдельные цепочки обещаний, которые полностью независимы друг от друга. При любом использовании обещаний в реальном мире эти две цепочки будут работать независимо, в свое собственное время и не иметь никакого отношения друг к другу.

jfriend00 19.06.2024 08:35

Существуют независимые цепочки обещаний, но в выводе должна быть некоторая логика, поскольку они используют одну и ту же очередь заданий. Ответ Николая правильный.

Shivam 19.06.2024 11:53
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
4
56
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Каждый вызов .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

Bergi 18.06.2024 22:39

Другие вопросы по теме