morsa
@morsa
Frontend-разработчик

Непонятное поведение своей интерпретации функции Promise.race, почему так происходит?

Всем привет. Давеча решал задачки на bigfrontend и дошел до своей реализации Promise.race. Хотя моя функцию и прошла все тесты на сервисе, но результат отличался от самого метода Promise.race.

Хотелось бы понять почему так.

// моковые данные
const promises = [
  Promise.reject('rejected1'),
  Promise.reject('rejected2'),
  new Promise((res, reject) => {
    setTimeout(() => res('resolvedTimeout'), 1000);
  }),
  Promise.resolve('resolved'),
];


Сначала я написал функцию так и она прошла тесты, но если в нее передать моковые данные, то вернется зарезолвенный promise cо строкой resolved. При этом, если передать эти входные данные в Promis.race, то естественное вернется отколненный промис rejected1.

const race = (promises) => {
  return new Promise((resolve, reject) => {
    const onFullfiled = (data) => {
      resolve(data);
    };

    const onRejected = (error) => {
      reject(error);
    };

    for (const promise of promises) {
      promise.then(onFullfiled).catch(onRejected);
    }
  });
};


Потом я переписал функцию так:

const race = (promises) => {
  return new Promise((resolve, reject) => {
    const onFullfiled = (data) => {
      resolve(data);
    };

    const onRejected = (error) => {
      reject(error);
    };

    for (const promise of promises) {
      promise.then(onFullfiled, onRejected);
    }
  });
};


Т.е отличие только в том, что фунция onRejected передается вторым аргументом в than. И при таком подходе, все работает как надо.

Очень хочется разобраться почему некорректно работает первый вариант
  • Вопрос задан
  • 262 просмотра
Решения вопроса 1
Alexandroppolus
@Alexandroppolus
кодир
строка
promise.then(onFullfiled).catch(onRejected);
на самом деле работает как
promise.then(onFullfiled, err => {throw err;}).then(v => v, onRejected);

Если имеем дело с зарезолвленным/зареджекченным промисом, то здесь первый then ставит микротаск в очередь сразу, а второй - только по выполнении микротаска от первого.

соответственно, для примера
const promises = [
  Promise.reject('rejected1'),
  Promise.reject('rejected2'),
  Promise.resolve('resolved'),
];


микротаски составили такую очередь:
1) err => {throw err;}
2) err => {throw err;}
3) onFullfiled
4) onRejected,
5) onRejected
6) v => v,


Где пункты 1-3 добавились на цикле, а 4-6 по мере выполнения первых трёх.

вот так и вышло, что onFullfiled вылез вперед.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы