组合承诺和非承诺值

Composing Promises and non-promise values

本文关键字:承诺 组合      更新时间:2023-09-26

我有一些基本上看起来像这样的代码:

let foos = ['foo', 'foo', 'foo'];
let bars = foos.map(foo => new Promise(resolve => resolve(foo + ' processed')));
function f(foo, bar) { '...' };

正如您所看到的,f()需要一个foo和一个bar参数。问题是barPromise。如果f()只需要bar,我会做:

Promise.all(bars).then(values => values.map(f));

然而,f()需要由Promise及其匹配的非承诺foo产生的bar值,所以我不确定编码这一点的最佳方式是什么?

.map也将元素的索引传递给回调,因此可以执行

Promise.all(bars).then(
   values => values.map((value, i) => f(foos[i], value))
);

如果foos不在Promise.all().then()处理程序的范围内,则需要确保foosbars都是沿着承诺链传递的。

以下是几种方法:

1.交付一系列对象

每个对象将包含一个foo及其对应的bar

let foos = ['foo', 'foo', 'foo'];
let promises = foos.map(foo => new Promise(resolve => resolve({
    unprocessed: foo,
    processed: foo + ' processed'
})));
// ...
Promise.all(promises).then(results => results.map(obj => f(obj.unprocessed, obj.processed)));

演示

2.交付阵列对象

该对象将包含一个foos数组和一个一致的bars数组。

let foos = ['foo', 'foo', 'foo'];
let promise = Promise.all(foos.map(foo => new Promise(resolve => resolve(foo + ' processed'))))
    .then(bars => ({ 'unprocessed': foos, 'processed': bars }));
// ...
promise.then(obj => obj.unprocessed.map((foo, i) => f(foo, obj.processed[i])));

演示

(1) 可以说没有(2)那么混乱。

(遵守评论中提到的foos不在范围内的限制…)

您可以使用ES6析构函数将额外的参数更平滑地传递到链中:

let foos = ['foo', 'foo', 'foo'];
let bars = foos.map(foo => new Promise(res => res([foo, foo + ' processed'])));
Promise.all(bars).then(values => values.map(([foo, bar]) => f(foo, bar)));