给出以下代码:
var arr = [1,2,3,4,5];
var results: number[] = await arr.map(async (item): Promise<number> => {
await callAsynchronousOperation(item);
return item + 1;
});
产生以下错误:
TS2322:类型'Promise <number> []'不能分配给类型'number []'。类型'Promise <number>不可分配给类型'number'。
我该如何解决?怎样才能让async await
和Array.map
一起工作?
这里的问题是您正在尝试await
兑现承诺而不是承诺。这没有达到您的期望。
当传递给的对象await
不是Promise时,await
只需立即按原样返回值,而不是尝试解析它。因此,由于您await
在此处传递了一个Promise对象的数组而不是Promise,因此await返回的值就是该数组,其类型为Promise<number>[]
。
您需要在此处执行的操作是调用Promise.all
返回的数组map
,以便在使用前将其转换为单个Promise await
。
该
Promise.all(iterable)
方法返回一个promise,当可迭代参数中的所有promise都已解决时,该promise会解决;或者以第一个传递的promise拒绝为由拒绝。
因此,在您的情况下:
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;
}));
这将解决您在此处遇到的特定错误。
如果您不使用本机Promises,而是使用Bluebird,则还有另一种解决方案。
您也可以尝试使用Promise.map(),将array.map和Promise.all混合使用
在您的情况下:
var arr = [1,2,3,4,5];
var results: number[] = await Promise.map(arr, async (item): Promise<number> => {
await callAsynchronousOperation(item);
return item + 1;
});
如果您映射到一个Promises数组,则可以将它们全部解析为一个数字数组。请参阅 Promise.all。
下面的解决方案以异步方式处理数组的所有元素并保留顺序:
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(n => calc(n));
const results = await Promise.all(unresolvedPromises);
};
asyncFunc();
也codepen。
请注意,我们仅“等待” Promise.all。我们多次调用calc而没有“ await”,并且立即收集了一系列未解决的Promise。然后Promise.all等待所有它们的解析,并按顺序返回具有已解析值的数组。
我建议如上所述使用Promise.all,但是如果您真的想避免这种方法,可以执行for或任何其他循环:
const arr = [1,2,3,4,5];
let resultingArr = [];
for (let i in arr){
await callAsynchronousOperation(i);
resultingArr.push(i + 1)
}
文章标签:async-await , ecmascript-2017 , javascript , promise , typescript
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!
评论已关闭!