javascript - 即使在等待 Promise.all() 也有待处理的承诺
问题描述
我很难理解为什么在等待Promise.all()之后我仍然有未决的承诺。
在下面的示例中,我通过在数组的每个元素上调用异步函数来创建一个 Promise 数组,使用.map()
.
现在,为什么承诺仍然显示为待处理?我现在(错误)理解它的方式:
then()
一旦 promise fromstoreData()
解决就触发storeData()
解决一次newDataArray
返回newDataArray
一旦里面的所有承诺promisesArray
都被解决或者一旦第一个被拒绝,就会返回。
storeData(OldDataArray).then(values => console.log(values))
// console shows:
// { id: 1, data: Promise { <pending> } },
// { id: 2, data: Promise { <pending> } }
const storeData = async (OldDataArray) => {
try {
const promisesArray = OldDataArray.map((item) => {
let newData = downloadMoreDetails(item.id, item.group); //async function, see below
return {
id: item.id,
data: newData,
};
});
const newDataArray = await Promise.all(promisesArray); // <-- I'm awaiting all promises to complete before assigning to newDataArray
return newDataArray;
} catch (error) {
console.log(error)
}
};
const downloadMoreDetails = async (id, group) => {
const response = await fetch(
`example.com/id/group.xml`
);
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`);
}
const str = await response.text();
const json = convert.xml2json(str, {
compact: true,
spaces: 2,
});
return json;
};
解决方案
newData
是一个承诺,但您正在等待一系列{id: item.id, data: newData }
. Promise.all()
不会在这些对象内部查找承诺并等待该承诺。它只看到一个普通对象数组,这意味着它无事可做。你可以通过这样做来解决这个问题:
const storeData = async (OldDataArray) => {
try {
const promisesArray = OldDataArray.map(async (item) => {
let newData = await downloadMoreDetails(item.id, item.group); //async function, see below
return {
id: item.id,
data: newData,
};
});
return Promise.all(promisesArray);
} catch (error) {
// log and rethrow error so the caller gets the rejection
console.log(error);
throw error;
}
};
这会将.map()
回调更改为async
. 这有两件有益的事情。首先,这意味着结果数组 from.map()
将是一个 Promise 数组,因为async
回调总是返回一个 Promise。其次,它允许您await
在回调内部使用,以便您可以使用实际数据填充返回的对象,而不是使用承诺。
请注意,您也可以在不添加以下内容的情况下完成它async/await
:
const storeData = (OldDataArray) => {
const promisesArray = OldDataArray.map((item) => {
return downloadMoreDetails(item.id, item.group).then(newData => {
return {
id: item.id,
data: newData,
};
});
});
return Promise.all(promisesArray).catch(error => {
// log and rethrow error so the caller gets the rejection
console.log(error);
throw error;
});
};
In this version, you directly return a promise from the .map()
callback and you make sure that promise resolves to your data object.
推荐阅读
- ios - 我更新了 taget 版本,但我的 App on Store 的兼容性仍然是“Ios 11 或更高版本”
- python - 如何在烧瓶中从 mongo db find 查询发送游标
- r - 如何将坐标列表转换为一个 SF Multipolygon?
- javascript - 如何清除 Slatejs v0.50+ 中的编辑器?
- windows - 添加客户端证书后,使用 Python 和 Postman 在 Windows 上“无法获取本地颁发者证书”
- php - 使用 Bootstrap 显示来自 DB 的结果
- go - gorm 使用 find 重新运行为空
- javascript - 以编程方式查找 chrome 中可用的最大可用缓存存储空间
- android - 应用程序设置允许通过移动网络下载?
- mysql - 将谷歌云存储连接到 mysql