You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

页面导出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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:57:14