Promise.allSettled в реализации Babel ES6

Я использую babel для перевода моего кода [email protected], и я застрял с promises.

Мне нужна функция allSettled -type, которую я мог бы использовать в q и bluebird или angular.$q, например.

В ядре babel-js Promise метода allSettled нет.

В настоящее время я использую q.allSettled в качестве обходного пути:

import { allSettled } from 'q';

Есть ли что-то подобное в babel polyfill? В качестве альтернативы, который является хорошим алгоритмом для меня, чтобы попытаться реализовать?

Ответ 1

В качестве альтернативы, который является хорошим алгоритмом для меня, чтобы попытаться реализовать?

  • создайте новое обещание с функцией
  • использовать массив счетчиков/результатов в объеме исполнителя
  • зарегистрировать обратный вызов then() с каждым родительским обещанием, сохраняя результаты в массиве
  • разрешить/отклонить обещание с шага 1, когда счетчик указывает, что выполнены все родительские promises

Ответ 2

2019 Ответ

Было предложение добавить эту функцию в стандарт ECMAScript, и оно было принято! Ознакомьтесь с документами Promise.allSettled.

Оригинальный ответ

Если вы посмотрите на реализацию q.allSettled, вы увидите, что на самом деле это довольно просто реализовать. Вот как вы можете реализовать это с помощью ES6 Promises:

function allSettled(promises) {
    let wrappedPromises = promises.map(p => Promise.resolve(p)
        .then(
            val => ({ status: 'fulfilled', value: val }),
            err => ({ status: 'rejected', reason: err })));
    return Promise.all(wrappedPromises);
}

Ответ 3

Здесь моя попытка на что-то подобное, у меня есть служба рассылки новостей, и в моем случае я хотел, чтобы мое обещание allSettled разрешалось с помощью массива всех результатов (отклонения и разрешения), В ЗАКАЗ, после того, как все адреса электронной почты будут урегулированы (все электронные письма исчезли):

Newsletter.prototype.allSettled = function(email_promises) {
    var allSettledPromise = new Promise(function(resolve, reject) {
        // Keep Count
        var counter = email_promises.length;

        // Keep Individual Results in Order
        var settlements = [];
        settlements[counter - 1] = undefined;

        function checkResolve() {
            counter--;
            if (counter == 0) {
                resolve(settlements);
            }
        }

        function recordResolution(index, data) {
            settlements[index] = {
                success: true,
                data: data
            };
            checkResolve();
        }

        function recordRejection(index, error) {
            settlements[index] = {
                success: false,
                error: error
            };
            checkResolve();
        }

        // Attach to all promises in array
        email_promises.forEach(function(email_promise, index) {
            email_promise.then(recordResolution.bind(null, index))
                .catch(recordRejection.bind(null, index));
        });
    });
    return allSettledPromise;
}

Ответ 4

Вот еще один вариант с той же функциональностью: spex.batch

Исходный код был бы слишком большой для повторной публикации здесь, так что вот пример из пакетная обработка о том, как его использовать:

var spex = require('spex')(Promise);

// function that returns a promise;
function getWord() {
    return Promise.resolve("World");
}

// function that returns a value;
function getExcl() {
    return '!';
}

// function that returns another function;
function nested() {
    return getExcl;
}

var values = [
    123,
    "Hello",
    getWord,
    Promise.resolve(nested)
];

spex.batch(values)
    .then(function (data) {
        console.log("DATA:", data);
    }, function (reason) {
        console.log("REASON:", reason);
    });

Выводится:

DATA: [ 123, 'Hello', 'World', '!' ]

Теперь давайте сделаем ошибку, изменив getWord на это:

function getWord() {
    return Promise.reject("World");
}

Теперь вывод:

REASON: [ { success: true, result: 123 },
  { success: true, result: 'Hello' },
  { success: false, result: 'World' },
  { success: true, result: '!' } ]

то есть. весь массив решен, сообщая результаты, связанные с индексами.

И если вместо того, чтобы сообщать всю причину, мы вызываем getErrors():

console.log("REASON:", reason.getErrors());

тогда выход будет:

REASON: [ 'World' ]

Это просто, чтобы упростить быстрый доступ к списку произошедших ошибок.