将一个已解决的 Promises 数组映射为一个值数组。

5

我有一个已解决 Promise 的数组:

[Promise, Promise, Promise, ...]

每个 Promise 解决后都会返回一个值。我该如何创建一个函数,使其返回这个 Promise 数组的映射,将每个 Promise 解决的值作为对应的值?

[value_1, value_2, value_3, ...]

这是我迄今为止的最接近答案:
const mapPromisesToValues = promises => {
    Promise.all(promises, values => {
        // how do I return these values from mapPromisesToValues
        return values
    });
}

更具体地说,我之所以问这个问题是因为我有一组 Promise 数组的集合。
const collection_1 = [Promise, Promise, Promise, ...];
const collection_2 = [Promise, Promise, Promise, ...];
//...

我想将这些映射为一组值的Promise批量处理成一个对象,并将其传递给另一个函数(在这种情况下是React的setState函数),该函数仅被调用一次。
this.setState({
    ...this.state,
    values_1,
    values_2,
    //...
});
3个回答

7
我有一个已解决的Promise数组... 如何从mapPromisesToValues返回这些值
即使您知道承诺已解决,也无法从函数中返回其值的映射。获取Promise的值的唯一方法是通过then回调,而该回调保证会异步调用,这意味着您的函数无法返回值;它只能返回值的Promise(例如,像Promise.all一样)。
您必须使函数返回Promise.all,并让函数使用者使用它。

关于您的编辑:

To be more specific, the reason why I ask is because I have a collection of arrays of Promises.

const collection_1 = [Promise, Promise, Promise, ...];
const collection_2 = [Promise, Promise, Promise, ...];

//...

and I want to batch these collection of promises mapped into a collection of values into 1 object, that I will then pass into another function that will be called once - in this case React's setState:

this.setState({
    ...this.state,
    values_1,
    values_2,
    //...
});

没问题,你不需要同步进行。只需要:

Promise.all([
    Promise.all(collection_1),
    Promise.all(collection_2),
    // etc.
])
.then(([values_1, values_2, /*etc*/]) => {
    this.setState({values_1, values_2,/*etc*/});
});

请注意我在那里省略了...this.state。两个原因:

  1. 如果您基于现有状态设置状态,则 必须使用回调版本的setState,而不是接受对象的版本;和

  2. 状态更新可以是部分的,因此...this.state是不必要的额外工作。


根据您的编程环境,您可能会发现采用async/await很有用(例如,如果您正在转码,或者您正在使用最新版本的Node.js)。async/await让您根据代码的逻辑流而不是同步流编写代码。在async函数中,您使用await来暂停函数并等待承诺解决。 async函数是返回承诺的函数的语法糖,await是消耗承诺的语法糖(例如,thencatch)。
为了从同步流过渡到逻辑流,请将入口点设置为您处理错误的async函数:
(async () => {
    // Your logical flow code here
}).catch(error => {
    // Handle the error
});

然后,您的函数可以是一个async函数:

async function example() {
    // ...
    return await Promise.all(thePromises)
}

...其他任何async函数都可以通过await使用:

let values = await example();

我看到你在每个集合周围都包装了Promise.all(),创建了一个Promise.all的集合。Promise.all()返回什么?这让我很头疼。 - jchi2241
这个完美地运行了,谢谢。我还有几个问题需要搞清楚 - then 函数的参数是一个值数组 - 这是某种形式的解构吗?我不知道你也可以解构数组。 - jchi2241
1
@jchi2241 - 你有多个Promise数组,因此上面的代码使用Promise.all等待数组中的所有Promise完成。由于我们正在处理多个数组,所以我们使用另一个Promise.all等待这些Promise.all中的所有Promise完成。最终的结果是一个数组的数组。你说得没错,当我们使用这个数组的数组时,我们使用解构将它们作为单独的数组参数而不是单个数组的数组参数接收。 - T.J. Crowder

1

遗憾的是,由于 Promise 的性质,您无法同步获取 Promise 的值。您需要执行以下操作:

const mapPromisesToValues = promises => {
  return Promise.all(promises);
}

mapPromisesToValues(promises).then(values => console.log(values));

0
const values = await Promise.all(promiseArr);

var a = new Promise(function(res, rej){res(5);}); var b = new Promise(function(res, rej){res(6);}); var d = await Promise.all([a,b]); console.log(d);变量a = new Promise(function(res, rej){res(5);}); 变量b = new Promise(function(res, rej){res(6);}); 变量d = await Promise.all([a,b]); console.log(d); - Ronn Wilder
对我来说,这是唯一正确的答案……我找不到任何添加其他内容的理由。我给你点赞。 - Michał Karpacki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接