19

babel用来转换我的node.js@0.10.x代码,但我坚持承诺。

我需要-type 功能,例如allSettled,我可以在其中使用。qbluebirdangular.$q

在 babel 的 core-jsPromise上,没有allSettled方法。

目前我正在使用q.allSettled作为解决方法:

import { allSettled } from 'q';

在 babel polyfill 中有类似的东西吗?或者,哪个是我尝试实现的好算法?

4

7 回答 7

39

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);
}
于 2016-08-19T04:17:15.510 回答
13

2020年答案:

其他答案试图做的是实现Promise.allSettled自己。这已经由core-js项目完成。

你需要做的是Promise.allSettled通过core-js为你制作 babel polyfill 。你配置它的方式是@babel/preset-env这样的:

presets: [
    ['@babel/preset-env', {
        useBuiltIns: 'usage',
        corejs: {version: 3, proposals: true},
    }],
],

在您的构建工件中,这将添加一个调用,require("core-js/modules/esnext.promise.all-settled")将monkeypatches.allSettled函数添加到promise API。

于 2020-03-16T10:29:00.387 回答
4
const allSettled = promises =>
  Promise.all(promises.map(promise => promise
    .then(value => ({ state: 'fulfilled', value }))
    .catch(reason => ({ state: 'rejected', reason }))
  ));

或者,如果您坚持要填充它:

if (Promise && !Promise.allSettled) {
  Promise.allSettled = function (promises) {
    return Promise.all(promises.map(function (promise) {
      return promise.then(function (value) {
        return { state: 'fulfilled', value: value };
      }).catch(function (reason) {
        return { state: 'rejected', reason: reason };
      });
    }));
  };
}

取自这里

于 2021-01-21T13:36:34.890 回答
2

或者,哪个是我尝试实现的好算法?

  1. 使用executor 函数创建一个新的Promise
  2. 在执行器范围内使用计数器/结果数组
  3. 向每个父承诺注册一个 then() 回调,将结果保存在数组中
  4. 当计数器指示所有父承诺都已完成时,从第 1 步解决/拒绝承诺
于 2015-06-01T11:51:41.170 回答
1

这是我对类似事情的尝试,我有 Newsletter 服务,在我的情况下,我希望我的 allSettled 承诺在所有email_promises都解决后(所有电子邮件都已经消失)解决所有结果(拒绝和解决)的数组出去):

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;
}
于 2015-10-07T04:29:21.480 回答
0

这是相同功能的另一种做法: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' ]

这只是为了简化对已发生错误列表的快速访问。

于 2015-10-15T05:47:41.180 回答
0

我的实现将在下面

Promise.prototype.myAllSettled = function (arr = []) {
  return new Promise(function processIterable(resolve, reject) {
    let result = [];
    arr.forEach((item) => {
      item
        .then((value) => {
          result.push({ status: "fulfilled", value: value });
          if (arr.length === result.length) resolve(result);
        })
        .catch((err) => {
          result.push({ status: "rejected", reason: `${err}` });
          if (arr.length === result.length) resolve(result);
        });
    });
  });
};
于 2020-06-01T19:10:08.297 回答