内存泄漏与pdf.js和铁列表

时间:2018-01-22 14:21:49

标签: javascript memory-leaks polymer-2.x pdf.js

在使用聚合物和pdf.js开发一些自定义元素来显示pdf文件时,我注意到在两个pdf文件之间显示和切换时出现内存泄漏。消耗的内存增长,我似乎无法弄清楚原因。为了观察内存更改,我在谷歌浏览器中使用堆快照。我们的想法是让铁列表显示单个页面,这些页面包含在另一个自定义元素中。

这是应该加载pdf文档的元素,将其显示为列表并将加载的pdfpageproxys传播到另一个自定义元素,然后应该显示它:

PDF一览viewer.html

<link rel="import" href="../polymer/polymer-element.html">
<link rel="import" href="../iron-list/iron-list.html">
<link rel="import" href="../layer-view/layer-view.html">
<link rel="import" href="../pdf-page-viewer/pdf-page-viewer.html">

<dom-module id="pdf-list-viewer">
  <template>
    <style>
      iron-list {
        width: 400ox;
        height: 800px;
      }

      layer-view {
        width: 100%;
        min-height: 100%;
      }
    </style>

    <iron-list items="[[pages]]" as="page">
      <template>
          <pdf-page-viewer pdf-page="[[page]]" canvas-width="800" />
      </template>
    </iron-list>
  </template>

  <script>
    /**
     * `pdf-list-viewer`
     * Shows a pdf file as a scrollable list of individual pages
     *
     * @customElement
     * @polymer
     * @demo demo/index.html
     */
    class PdfListViewer extends Polymer.Element {
      static get is() { return 'pdf-list-viewer'; }
      static get properties() {
        return {
          pdfUrl: {
            type: Object,
            observer: '_pdfUrlChanged'
          },
          pages: {
            type: Array,
            value: []
          },
          _loadingTask: Object
        };
      }

      _pdfUrlChanged(newValue, oldValue) {
        var self = this;
        // Remove old pages
        var destroyPromise = null;
        if (this.pages.length !== 0) {
          destroyPromise = this._loadingTask.destroy();
        }
        if(destroyPromise === null){
          this._loadPdf(newValue);
        } else{
          destroyPromise.then(function(){
            self._loadPdf(newValue);
          });
        }

      }

      _loadPdf(newUrl){
        var self = this;
        this.pdfUrl = newUrl;

        this._loadingTask = PDFJS.getDocument({ url: newUrl });
        this._loadingTask.then(function (pdfDoc) {
          var pagePromises = Array.from(new Array(pdfDoc.numPages), (_, index) => pdfDoc.getPage(index + 1));
          Promise.all(pagePromises).then(function (values) {
            self.splice('pages', 0, self.pages.length, ...values);
          });
        }).catch(function (error) {
          // TODO: handle error
          alert(error.message);
        });
      }
    }

    window.customElements.define(PdfListViewer.is, PdfListViewer);
  </script>
</dom-module>

这是一个只需要在画布上显示pdf并处理缩放的元素(这对于现在来说并不重要):

PDF的页面viewer.html

<link rel="import" href="../polymer/polymer-element.html">
<linkrel="import" href="../paper-spinner/paper-spinner.html">
<link rel="import" href="pdfjs.html">

  <dom-module id="pdf-page-viewer">
    <template>
      <style>
      </style>
      <canvas id="pageCanvas" width="[[canvasWidth]]"></canvas>
      <!-- Here should be a circular loading bar displaying that page is rendering -->
    </template>

    <script>
      /**
       * `pdf-page-viewer`
       * Viewer to display a single pdf page using mozillas pdf.js library
       *
       * @customElement
       * @polymer
       * @demo demo/index.html
       */
      class PdfPageViewer extends Polymer.Element {
        static get is() { return 'pdf-page-viewer'; }
        static get properties() {
          return {
            /**
             * Page object as defined in pdfjs-dist library in lib/core/document.js. 
             */
            pdfPage: {
              type: Object,
              observer: '_pageChanged'
            },
            /**
             * Width of the page canvas in pixel. Height will be calculated when showing the page.
             */
            canvasWidth: Number,
            _zoom: Number,
            /**
             * Displays wether or not a page rendering is being processed.
             */
            pageRenderingInProgress: {
              type: Boolean,
              value: false,
            }
          };
        }
        constructor(){
          super();
          this._boundChangeListener = this.zoom.bind(this);
        }

        connectedCallback() {
          super.connectedCallback();

          window.addEventListener('zoom', this._boundChangeListener);
        }

        disconnectedCallback(){
          super.disconnectedCallback();

          window.removeEventListener('zoom', this._boundChangeListener);
        }

        _pageChanged(newValue, oldValue) {
          this.pdfPage = newValue;
          this._showPage();
        }


        // Load and render a specific page of the PDF
        _showPage() {
          this.pageRenderingInProgress = true;
          var self = this;
          // As the canvas is of a fixed width we need to set the scale of the viewport accordingly
          var scale_required = this.$.pageCanvas.width / this.pdfPage.getViewport(1).width;

          // Get viewport of the page at required scale
          var viewport = this.pdfPage.getViewport(scale_required);

          // Set canvas height
          this.$.pageCanvas.height = viewport.height;

          var renderContext = {
            canvasContext: self.$.pageCanvas.getContext('2d'),
            viewport: viewport
          };

          // Render the page contents in the canvas
          this.dispatchEvent(new CustomEvent('pageRenderingStarted'));
          this.pdfPage.render(renderContext).then(function () {
            self.pageRenderingInProgress = false;
            self.dispatchEvent(new CustomEvent('pageRenderingFinished'));
          });
        }

        zoom(event) {
          this._zoom = event.detail.newValue;
          this.$.pageCanvas.width = this.canvasWidth * this._zoom;

          this._showPage();
        }
      }

      window.customElements.define(PdfPageViewer.is, PdfPageViewer);
    </script>
  </dom-module>

请记住,我是网络开发中的新生物(以及聚合物和pdf.js),所以可以随意批评你发现的每一件小事,这样我就可以在这方面有所改进。 非常感谢每一个帮助!

修改

我使用chrome dev工具监视this webcomponent中pdf-viewer演示的内存使用情况,并在拍摄内存堆快照时注意到相同的内存泄漏。只需转到https://www.webcomponents.org/element/telecomsante/pdf-viewer/demo/demo/index.html,单击367页的pdf文件,在保管箱中切换到antoher pdf并切换回367 pdf文档。再次通过它们后,您将获得以下增加:

22,5 MB(第1/367页已打开) - &gt;

52,7 MB(点击文档的每一页) - &gt;

55,5 MB(在列表中打开另一个文档并单击页面) - &gt;

69,8 MB(打开367页pdf并再次点击所有这些页面)

有什么想法吗? 要重新创建,只需

0 个答案:

没有答案