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

Ссылка скопирована
1 ответ

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

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

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

// моковые данные 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).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);     }   }); };

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. И при таком подходе, все работает как надо.

Очень хочется разобраться почему некорректно работает первый вариант

Дополнительно:

Оборачивать resolve и reject в ещё одну функцию нет необходимости.

строка
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'), ];

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) err => {throw err;} 2) err => {throw err;} 3) onFullfiled 4) onRejected, 5) onRejected 6) v => v,

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

вот так и вышло, что onFullfiled вылез вперед.

  • Теперь ясно. Большое спасибо!)
Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Роман IT Ответ

Проблема, с которой вы столкнулись, может быть вызвана различными причинами. Давайте разберем, как работает функция Promise.race и почему возможно непонятное поведение.

Функция Promise.race принимает массив промисов и возвращает новый промис, который завершится с результатом или ошибкой первого выполненного промиса из массива. Это означает, что если один из промисов завершится раньше остальных, результат этого промиса будет использован для завершения промиса, возвращаемого функцией Promise.race.

Однако, возможно, что у вас возникает непонятное поведение из-за того, что не все промисы в массиве завершаются корректно или не возвращают значения. Если один из промисов завершается с ошибкой, это может привести к тому, что результатом Promise.race будет ошибка, даже если другие промисы завершились успешно.

Также стоит учитывать, что Promise.race не останавливает выполнение других промисов из массива, когда один из них завершается. Это может быть причиной непредсказуемого поведения, если вы ожидаете остановку выполнения после завершения первого промиса.

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

Пример использования Promise.race с массивом промисов в PHP:

$promise1 = new Promise(function ($resolve, $reject) {
    // асинхронная операция
    $resolve('Результат промиса 1');
});
 
$promise2 = new Promise(function ($resolve, $reject) {
    // асинхронная операция
    $resolve('Результат промиса 2');
});
 
Promise::race([$promise1, $promise2])
    ->then(function ($value) {
        echo $value; // выведет 'Результат промиса 1' или 'Результат промиса 2' в зависимости от того, какой промис завершится первым
    })
    ->catch(function ($error) {
        echo $error; // обработка ошибки, если один из промисов завершится с ошибкой
});

$promise1 = new Promise(function ($resolve, $reject) { // асинхронная операция $resolve('Результат промиса 1'); }); $promise2 = new Promise(function ($resolve, $reject) { // асинхронная операция $resolve('Результат промиса 2'); }); Promise::race([$promise1, $promise2]) ->then(function ($value) { echo $value; // выведет 'Результат промиса 1' или 'Результат промиса 2' в зависимости от того, какой промис завершится первым }) ->catch(function ($error) { echo $error; // обработка ошибки, если один из промисов завершится с ошибкой });

Надеюсь, эта информация поможет вам разобраться с непонятным поведением функции Promise.race. Если у вас остались вопросы, не стесняйтесь задавать их.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно