如何使用 Promise.all() 解析嵌套的 Promise

问题描述 投票:0回答:3

我正在尝试写这样的东西,但无法解决内心的承诺。

  const traceSamplesRequests = transactionTypes.map(async (transactionType) => {
    // This part should be synchronous since we need transactionNames
    const transactionNames = await api.getTransactionNames();
    return transactionNames.map((transactionName) => api.getTraceSamples());
  });

我想用 Promise 编写 lambda 函数。所有的都不是命令式循环。

javascript async-await promise es6-promise
3个回答
3
投票

所以,

.map()
不是承诺感知的。它调用回调,并尽职尽责地收集回调的返回值,然后前进到循环的下一次迭代。由于您的回调是
async
,其中包含
await
,因此该返回值是一个未解决的承诺。所以,你从
.map()
得到的是一系列承诺。

因此,如果不使用某些东西来等待承诺,就无法使用

.map()
或任何数组迭代方法。

听起来您已经知道这一点,但是使用您拥有的代码,您将插入两个

Promise.all()
语句:

  const traceSamplesRequests = await Promise.all(transactionTypes.map(async (transactionType) => {
    // This part should be synchronous since we need transactionNames
    const transactionNames = await api.getTransactionNames();
    return Promise.all(transactionNames.map((transactionName) => api.getTraceSamples()));
  }));

这将为您提供一个值数组(并且父函数必须是

async
)。这将并行运行循环中的所有异步操作(所有操作同时进行)。

您的其他选择是使用

for
while
循环,它将暂停每个
await
的循环迭代,并按顺序运行异步操作(循环的第二次迭代在第一个迭代完成之前不会运行)。

或者,您可以编写某种辅助函数,它是

.map()
的承诺感知版本。不过,您可能只是在辅助函数中使用
for
.map()
Promise.all()

Async Promise 库有多个这样的辅助函数作为选择使用。它们被设计为与 Promise 或普通回调一起使用。


0
投票
我实际上是这样工作的:

const traceSamplesRequests = await Promise.all( transactionTypes.map(async (transactionType) => { const transactionNames = await api.getTransactionNames({ transactionType }); return await Promise.all(transactionNames.map((transactionName) => api.getTraceSamples({ transactionType }))); }) );
    

0
投票
我正在使用一个函数来解决任何可以找到它的嵌套承诺。

function hasNestedPromises(value: unknown): boolean { if (value instanceof Promise) { return true } else if (Array.isArray(value)) { return value.some(hasNestedPromises) } else if (value && typeof value === 'object') { return Object.values(value).some(hasNestedPromises) } return false } export function reolsveNestedPromises(value: unknown): unknown | Promise<unknown> { //not very efficient but in order to avoid process object like Set, Date, ecc we need to perform this check every time if (!hasNestedPromises(value)) { return value } if (value instanceof Promise) { return value.then(reolsveNestedPromises) } else if (Array.isArray(value)) { return Promise.all(value.map(reolsveNestedPromises)) } else if (value && typeof value === 'object') { return Promise.all(Object.values(value).map(reolsveNestedPromises)).then((values) => { return Object.fromEntries(Object.keys(value).map((key, index) => [key, values[index]])) }) } return value }
    
© www.soinside.com 2019 - 2024. All rights reserved.