oehaut
oehaut

Reputation: 129

Getting an infinite loop from set function in ember.js

I am trying to display a div with the class loader only while a PDF page is loading.

It works, but somehow the function this.displayPage(pdf,1) is getting looped over.

After renderPage(page) is called, it goes back to didRender() > this.displayPage(pdf,1).

This only happens when I use set(this, 'pageIsRendering', false/true) so I'm thinking my problem might have to do with this.

I tried debugging my code but I don't understand what's creating the loop.

I am using PDFJS library to display the PDF document.

Here is my component.js code

  pageisRendered: true,
  pageIsRendering: false,

  didRender() {
    pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdf.worker.js';
    set(this, 'setPageValueInput', document.querySelector('.set-page-value'));
    let pdfDoc = pdfjsLib.getDocument(this.url).then(pdf => {
      this.displayPage(pdf, 1);
      this.shownPdf = pdf;
      document.querySelector('.total-page-number').value = this.shownPdf.numPages;
    });
  },

  displayPage(pdf, num) {
    set(this, 'pageIsRendering', true);
    pdf.getPage(num).then(page => {
      if (this.pageisRendered) {
        this.pageisRendered = false;
        this.renderPage(page);
      }
    });
  },

  renderPage(page) {
    let scale = this.pdfScale; // render with global pdfScale variable
    let canvas = document.querySelector('.pdf-canvas');
    let context = canvas.getContext('2d');
    let viewport = page.getViewport(scale);
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    let renderContext = {
      canvasContext: context,
      viewport
    };
    page.render(renderContext).then(() => {
      this.pageisRendered = true;
      set(this, 'pageIsRendering', false);
    });
  },

Here is my html code

<div class="pdf-container ">
    <div class="canvas-container">
        {{#if pageIsRendering}}
          <div class="loader">
            {{loading-spinner isLoading="true"}}
          </div>
        {{/if}}
    </div>
</div>

Upvotes: 0

Views: 339

Answers (1)

Your displayPage will call renderPage which causes a render which will trigger didRender again most likely therefore causing infinite loop.

I think you just need a single flag to track if the page is rendered. If it is, then don't trigger didRender again. Alternatively you should consider using another event instead of didRender such as init.

  pageisRendered: false,

  didRender() {
    if (this.pageisRendered) {
        return;
    }

    pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdf.worker.js';
    set(this, 'setPageValueInput', document.querySelector('.set-page-value'));
    let pdfDoc = pdfjsLib.getDocument(this.url).then(pdf => {
      this.displayPage(pdf, 1);
      this.shownPdf = pdf;
      document.querySelector('.total-page-number').value = this.shownPdf.numPages;
    });
  },

  displayPage(pdf, num) {
    pdf.getPage(num).then(page => {
        this.renderPage(page);
    });
  },

  renderPage(page) {
    let scale = this.pdfScale; // render with global pdfScale variable
    let canvas = document.querySelector('.pdf-canvas');
    let context = canvas.getContext('2d');
    let viewport = page.getViewport(scale);
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    let renderContext = {
      canvasContext: context,
      viewport
    };
    page.render(renderContext).then(() => {
      set(this, 'pageisRendered ', true);
    });
  },

Upvotes: 1

Related Questions