如何解决Promise.allSettled无法等待嵌套内部Promise执行完成的问题
问题原因
你遇到的问题本质是exportVisualData函数没有把内部嵌套的Promise链正确返回,也没有收集所有异步操作的状态:
- 你在
pages.forEach、visualDescriptors.forEach里触发的异步函数(getVisuals、setActive、exportData)都没有被外层Promise跟踪,forEach本身不会等待异步操作完成,也不会收集返回的Promise - 整个函数的返回Promise在
getPages执行完就直接resolve了,根本不会等内部的异步逻辑跑完,所以拿到的value永远是undefined
修正方案
你需要把所有内部异步操作的Promise都收集起来,层层返回,让外层Promise等待所有操作完成再结束,修改后的exportVisualData代码如下:
function exportVisualData(id: string): Promise<void | IExportDataResult> { // 用return把整个Promise链传递出去 return report!.getPages().then((pages) => { // 把每个page对应的异步操作Promise收集成数组 const pagePromises = pages.map((page) => { // 返回每个page的getVisuals异步操作 return page.getVisuals().then((visualDescriptors) => { // 收集每个visual对应的异步操作Promise const visualPromises = visualDescriptors.map((visualDescriptor) => { if (visualDescriptor.name !== id) return Promise.resolve(); // 匹配到对应id的visual时,返回对应的异步链 if (!page.isActive) { return page.setActive().then(() => { return visualDescriptor?.exportData(ExportDataType.Summarized); }); } else { return visualDescriptor?.exportData(ExportDataType.Summarized); } }); // 等待当前page下所有visual的异步操作完成 return Promise.all(visualPromises); }); }); // 等待所有page的异步操作完成,把结果返回给外层 return Promise.all(pagePromises); }); }
优化建议
如果你不想最后拿到的结果是多层嵌套的数组,也可以用async/await语法改写,找到匹配的visual之后直接返回结果,不需要遍历所有剩余元素,可读性和性能都更好:
function exportVisualData(id: string): Promise<void | IExportDataResult> { return report!.getPages().then(async (pages) => { for (const page of pages) { const visualDescriptors = await page.getVisuals(); const targetVisual = visualDescriptors.find(v => v.name === id); if (targetVisual) { if (!page.isActive) await page.setActive(); return targetVisual.exportData(ExportDataType.Summarized); } } }); }
修改完成后Promise.allSettled就能正确等待exportVisualData所有异步逻辑执行完毕,拿到对应的返回结果。
内容的提问来源于stack exchange,提问作者Higune
相关产品推荐
相关产品推荐

