Sathya
Sathya

Reputation: 51

Page is getting unresponsive while generating the export pdf button

Page is getting unresponsive while exporting the page into pdf, refer the below screenshot.

enter image description here

Here is the stackblitz code: The below code is used to convert the chart into image which is causing the performnce issue.

  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) => { // It is taking more time to convert chart to image which sometimes makes the page unresponsiveness

    const pngImgage = document.createElement('img');
    pngImgage.src = image;
    chartElementRef.innerHTML = '';
    chartElementRef.appendChild(pngImgage);
    this.validateChartsRenderedAndGeneratePdf(
      i,
      listOfCharts,
      reportLayoutElement
    );
  });
}

}

Please help me here to solve page unresponsive error.

Expected Results: Should not display page unresponsive error while generating the pdf.

Upvotes: 1

Views: 174

Answers (2)

Kourosh Raoufi
Kourosh Raoufi

Reputation: 1652

This issue didn't happen because of performance. It occurred because you ran your long-processing code on the Main Thread

The main thread is where a browser processes user events and paints. By default, the browser uses a single thread to run all the JavaScript in your page, as well as to perform layout, reflows, and garbage collection. This means that long-running JavaScript functions can block the thread, leading to an unresponsive page and a bad user experience.

so it will completely freeze and block your UI during the iteration and PDF generation.

JavaScript used to be a single-threaded language, so the only way to run long-processing tasks was by using setTimeout (as mentioned in the previous answer). This approach chunks the process and adds them to the stack, allowing the user to interact with the browser UI simultaneously.

function myFunctionWithCallback(a, b, callback) {
  setTimeout(() => {
    // Do something
    const c = a + b
 
    // Call the callback
    if(callback && callback instanceof Function) {
      callback(c)
    }
  }, 0)
}

myFunctionWithCallback(1, 2, (result) => console.log(result))
console.log('Waiting for the result...')

Nowadays, it is also possible to achieve this with Promises and Web Workers.

useful articles:

Upvotes: 0

Pykara_Developer
Pykara_Developer

Reputation: 318

Please replace the below function:

 private convertChartToPng(listOfCharts: any, reportLayoutElement: any) {
    const processChunk = (index: number) => {
      if (index < listOfCharts.length) {
        const chartCtrlId = '#' + listOfCharts[index].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(
            index,
            listOfCharts,
            reportLayoutElement
          );
          setTimeout(() => processChunk(index + 1), 0);
        });
      }
    };
    processChunk(0);
  }

Upvotes: 3

Related Questions