页面导出PDF时无响应问题求助(附代码及截图)
导出PDF时页面无响应问题解决
导出PDF时页面出现无响应情况,截图如下:
经排查,是图表转图片的逻辑引发性能问题,相关代码如下:
private convertChartToPng(listOfCharts: any, reportLayoutElement: any) { for (let i = 0; i < listOfCharts.length; i++) { const chartCtrlId = '#' + listOfCharts[i].id; const chartElementRef = reportLayoutElement.querySelector(chartCtrlId); this.convertChartToImg(chartCtrlId).subscribe((image) => { // 该图表转图片操作耗时较长,有时会导致页面无响应 const pngImgage = document.createElement('img'); pngImgage.src = image; chartElementRef.innerHTML = ''; chartElementRef.appendChild(pngImgage); this.validateChartsRenderedAndGeneratePdf( i, listOfCharts, reportLayoutElement ); }); } }
问题核心
同步循环中并行发起多个耗时的转图请求,导致主线程被长时间阻塞,浏览器无法响应用户操作,最终触发无响应提示。
优化方案
1. 串行处理转图请求
避免同时执行多个转图操作,改为完成一个再处理下一个,减少主线程压力:
import { firstValueFrom } from 'rxjs'; private async convertChartToPng(listOfCharts: any, reportLayoutElement: any) { for (let i = 0; i < listOfCharts.length; i++) { const chartCtrlId = '#' + listOfCharts[i].id; const chartElementRef = reportLayoutElement.querySelector(chartCtrlId); // 将Observable转为Promise,用await实现串行执行 const image = await firstValueFrom(this.convertChartToImg(chartCtrlId)); const pngImage = document.createElement('img'); pngImage.src = image; chartElementRef.innerHTML = ''; chartElementRef.appendChild(pngImage); this.validateChartsRenderedAndGeneratePdf(i, listOfCharts, reportLayoutElement); } }
(注:RxJS 6及以下版本可使用toPromise()替代firstValueFrom)
2. 分批处理+让出主线程
如果需要一定程度的并行处理,可将图表分成小批次,每处理完一批后用setTimeout给浏览器留出响应时间:
private convertChartToPng(listOfCharts: any, reportLayoutElement: any) { const batchSize = 2; // 每次处理2个图表,可根据实际情况调整 let currentIndex = 0; const processBatch = () => { const endIndex = Math.min(currentIndex + batchSize, listOfCharts.length); for (let i = currentIndex; i < endIndex; i++) { const chartCtrlId = '#' + listOfCharts[i].id; const chartElementRef = reportLayoutElement.querySelector(chartCtrlId); this.convertChartToImg(chartCtrlId).subscribe((image) => { const pngImage = document.createElement('img'); pngImage.src = image; chartElementRef.innerHTML = ''; chartElementRef.appendChild(pngImage); this.validateChartsRenderedAndGeneratePdf(i, listOfCharts, reportLayoutElement); }); } currentIndex = endIndex; if (currentIndex < listOfCharts.length) { setTimeout(processBatch, 100); // 延迟100ms处理下一批,让出主线程 } }; processBatch(); }
3. 优化转图逻辑本身
- 检查
convertChartToImg方法,是否存在重复绘制、冗余计算,可针对性优化; - 导出PDF时可降低图片分辨率(比如将canvas尺寸按比例缩小),减少转图耗时;
- 对已转换过的图表进行缓存,避免重复转换。
4. 使用Web Worker(进阶方案)
将转图的核心计算逻辑(如canvas绘制)移到Web Worker中执行,完全避免阻塞主线程。注意Worker中无法直接操作DOM,需将生成的图片数据传递回主线程后再更新页面。
内容的提问来源于stack exchange,提问作者Sathya
相关产品推荐
相关产品推荐

