将异步等待与 Array.map 一起使用

给定以下代码:

var arr = [1,2,3,4,5];

var results: number[] = await arr.map(async (item): Promise<number> => {
        await callAsynchronousOperation(item);
        return item + 1;
    });

这将产生以下错误:

TS2322: 类型“承诺<数字>[]”不能分配给类型“数字[]”。键入“承诺<数字>不能分配给类型”数字”。

我该如何修复它?我怎样才能一起制作和工作?async awaitArray.map


答案 1

这里的问题是,你试图得到一系列的承诺,而不是一个承诺。这不会达到您的预期。await

当传递给的对象不是 Promise 时,只需立即按原样返回值,而不是尝试解析它。因此,由于您在此处传递了一个数组(Promise对象)而不是Promise,因此 await 返回的值只是该数组,其类型为 。awaitawaitawaitPromise<number>[]

您可能想做的是调用 返回的数组,以便在它之前将其转换为单个 Promise。Promise.allmapawait

根据 Promise.all 的 MDN 文档

该方法返回一个承诺,当可迭代参数中的所有承诺都已解决时,该承诺将解决,或者以拒绝的第一个传递的承诺为由拒绝。Promise.all(iterable)

因此,在您的情况下:

var arr = [1, 2, 3, 4, 5];

var results: number[] = await Promise.all(arr.map(async (item): Promise<number> => {
    await callAsynchronousOperation(item);
    return item + 1;
}));

这将解决您在此处遇到的特定错误。

根据您要尝试的确切内容,您也可以考虑使用Promise.allSettledPromise.anyPromise.race而不是,尽管在大多数情况下(几乎肯定包括这个)将是您想要的那个。Promise.allPromise.all


答案 2

下面的解决方案是正确同时使用异步 await 和 Array.map。并行、异步地处理数组的所有元素并保留顺序:

const arr = [1, 2, 3, 4, 5, 6, 7, 8];

const randomDelay = () => new Promise(resolve =>     setTimeout(resolve, Math.random() * 1000));

const calc = async n => {
  await randomDelay();
  return n * 2;
};

const asyncFunc = async() => {
  const unresolvedPromises = arr.map(calc);
  const results = await Promise.all(unresolvedPromises);
  document.write(results)
};

document.write('calculating...')
asyncFunc();

也是编解码器。

请注意,我们只是“等待”Promise.all。我们多次调用不带“await”的 calc,并立即收集一系列未解决的承诺。然后 Promise.all 等待所有这些问题的解析,并返回一个数组,其中包含按顺序解析的值。