给定以下代码:
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'。
我该怎么解决呢?我如何使异步等待和数组。地图一起工作?
这里的问题是,你试图等待一连串的承诺,而不是一个承诺。这并不是你所期望的。
当传递给await的对象不是Promise时,await只是立即返回值,而不是试图解析它。因此,由于这里传递给await的是一个(Promise对象的)数组而不是一个Promise对象,await返回的值就是这个数组,它的类型是Promise<number>[]。
你可能要做的就是给承诺打电话。为了在等待它之前将它转换为单个Promise。
根据Promise.all的MDN文档:
promise .all(iterable)方法返回一个可解析的promise
当iterable实参中的所有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;
}));
这将解决您在这里遇到的特定错误。
根据您想要做的具体内容,您也可以考虑使用Promise。allSettled,承诺。任何,或承诺。竞赛而不是承诺。所有的,尽管在大多数情况下(几乎肯定包括这个)承诺。一切都会是你想要的。
我在BE方面有一个任务,从回购中找到所有实体,并添加一个新的属性url并返回到控制器层。这就是我如何做到的(感谢Ajedi32的回应):
async findAll(): Promise<ImageResponse[]> {
const images = await this.imageRepository.find(); // This is an array of type Image (DB entity)
const host = this.request.get('host');
const mappedImages = await Promise.all(images.map(image => ({...image, url: `http://${host}/images/${image.id}`}))); // This is an array of type Object
return plainToClass(ImageResponse, mappedImages); // Result is an array of type ImageResponse
}
注意:Image(实体)没有属性url,但imagerresponse -有
我推荐使用Promise。如上所述,但如果你真的想避免这种方法,你可以做一个for循环或任何其他循环:
const arr = [1,2,3,4,5];
let resultingArr = [];
for (let i in arr){
await callAsynchronousOperation(i);
resultingArr.push(i + 1)
}
供参考:如果你想迭代数组的项,而不是索引(@ralfoide的评论),在arr语句中使用of而不是in inside let i。