Promise.allSettled 在 babel ES6 实现中
Promise.allSettled in babel ES6 implementation
我正在使用 babel
转译我的 node.js@0.10.x
代码,但我受困于 promises。
我需要可以在 q
和 bluebird
或 angular.$q
中使用的 allSettled
类型的功能。
在 babel 的 core-js Promise
上,没有 allSettled
方法。
目前我正在使用 q.allSettled
作为解决方法:
import { allSettled } from 'q';
babel polyfill 中有类似的东西吗?或者,哪个算法适合我尝试实施?
Alternatively, which is a good algorithm for me to try to implement?
- 使用 executor function
创建一个新的承诺
- 在执行器范围内使用一个counter/result数组
- 注册一个 then() 回调,每个父承诺将结果保存在数组中
- resolve/reject 当计数器指示所有父承诺都已完成时从步骤 1 开始承诺
这是我对类似事情的尝试,我有新闻通讯服务,在我的例子中,我希望我的 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;
}
这是对相同功能的另一种看法:spex.batch
使用方法source code would be too much to re-post here, so here's just an example from the batch processing:
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' ]
这只是为了简化对所发生错误列表的快速访问。
2019 年答案
详情有a proposal to add this function to the ECMAScript standard, and it has been accepted! Check out the Promise.allSettled
docs。
原答案
如果您看一下 implementation of 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);
}
2020 年答案:
其他答案试图做的是自己实施 Promise.allSettled
。这已经由 core-js 项目完成。
你需要做的是通过 core-js 为你制作 babel polyfill Promise.allSettled
。你配置它的方式是通过 @babel/preset-env
像这样:
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: {version: 3, proposals: true},
}],
],
在您的构建工件中,这将添加对 require("core-js/modules/esnext.promise.all-settled")
的调用,该调用将 .allSettled
函数猴子修补到承诺 API.
我的实现如下
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);
});
});
});
};
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 };
});
}));
};
}
取自here
我正在使用 babel
转译我的 node.js@0.10.x
代码,但我受困于 promises。
我需要可以在 q
和 bluebird
或 angular.$q
中使用的 allSettled
类型的功能。
在 babel 的 core-js Promise
上,没有 allSettled
方法。
目前我正在使用 q.allSettled
作为解决方法:
import { allSettled } from 'q';
babel polyfill 中有类似的东西吗?或者,哪个算法适合我尝试实施?
Alternatively, which is a good algorithm for me to try to implement?
- 使用 executor function 创建一个新的承诺
- 在执行器范围内使用一个counter/result数组
- 注册一个 then() 回调,每个父承诺将结果保存在数组中
- resolve/reject 当计数器指示所有父承诺都已完成时从步骤 1 开始承诺
这是我对类似事情的尝试,我有新闻通讯服务,在我的例子中,我希望我的 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;
}
这是对相同功能的另一种看法:spex.batch
使用方法source code would be too much to re-post here, so here's just an example from the batch processing:
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' ]
这只是为了简化对所发生错误列表的快速访问。
2019 年答案
详情有a proposal to add this function to the ECMAScript standard, and it has been accepted! Check out the Promise.allSettled
docs。
原答案
如果您看一下 implementation of 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);
}
2020 年答案:
其他答案试图做的是自己实施 Promise.allSettled
。这已经由 core-js 项目完成。
你需要做的是通过 core-js 为你制作 babel polyfill Promise.allSettled
。你配置它的方式是通过 @babel/preset-env
像这样:
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: {version: 3, proposals: true},
}],
],
在您的构建工件中,这将添加对 require("core-js/modules/esnext.promise.all-settled")
的调用,该调用将 .allSettled
函数猴子修补到承诺 API.
我的实现如下
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);
});
});
});
};
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 };
});
}));
};
}
取自here