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

使用pdf.js与iron-list开发PDF组件时的内存泄漏问题求助

Hey there, let's dig into this memory leak issue you're facing with your Polymer + pdf.js PDF viewer. I've worked through similar problems before, so let's break this down step by step.

Common Memory Leak Culprits in Your Setup

Based on your description (using iron-list with custom pdf-page-viewer elements) and the third-party demo behavior, the leaks almost always boil down to uncleaned resources from pdf.js or incomplete component lifecycle handling. Here are the key areas to check:

1. Uncleaned pdf.js Resources

pdf.js creates heavy objects like PDFPageProxy (for rendered pages) and PDFDocumentProxy (for the entire PDF) that won't be garbage collected unless explicitly destroyed. If you're not cleaning these up:

  • Old page instances stick around when switching pages or PDFs
  • Canvas elements used for rendering aren't cleared or removed from memory
  • Event listeners attached to pdf.js events (like page load) aren't detached

2. Missing Polymer Component Cleanup

Polymer elements have lifecycle hooks that you need to use to tear down resources. If your pdf-page-viewer doesn't handle cleanup when it's removed from the DOM:

  • The element and its internal objects (like pdf.js instances) stay referenced in memory
  • iron-list's element reuse feature can cause old page data to linger in reused components

3. iron-list Reuse Gotchas

iron-list reuses list items to optimize performance, but this can lead to memory leaks if you don't reset component state:

  • When a pdf-page-viewer is reused to display a new page, the old page's pdf.js instance and canvas data aren't cleared
  • Cached component state piles up as you browse multiple pages or switch PDFs

Specific Fixes & Code Improvements

Let's translate these issues into actionable fixes for your components:

Fix 1: Add Cleanup Logic to pdf-page-viewer

Update your pdf-page-viewer element to clean up pdf.js resources when it's disconnected from the DOM:

class PdfPageViewer extends Polymer.Element {
  static get is() { return 'pdf-page-viewer'; }

  // ... your existing code ...

  disconnectedCallback() {
    super.disconnectedCallback();
    
    // Destroy the pdf.js page instance (critical for memory release)
    if (this.pdfPage) {
      this.pdfPage.destroy();
      this.pdfPage = null;
    }

    // Clear and remove canvas to free up GPU memory
    if (this.$.pdfCanvas) {
      const ctx = this.$.pdfCanvas.getContext('2d');
      ctx.clearRect(0, 0, this.$.pdfCanvas.width, this.$.pdfCanvas.height);
      this.$.pdfCanvas.remove();
    }

    // Detach any event listeners you added to pdf.js or DOM elements
    if (this.pageLoadListener) {
      this.pageLoadListener(); // Use the reference from addEventListener to remove it
    }
  }
}

Fix 2: Reset State When iron-list Reuses Components

When iron-list reuses a pdf-page-viewer for a new page, make sure you clean up old resources before loading the new page:

class PdfPageViewer extends Polymer.Element {
  // ... your existing code ...

  static get properties() {
    return {
      pageNumber: {
        type: Number,
        observer: '_pageNumberChanged'
      },
      pdfDoc: {
        type: Object
      }
    };
  }

  _pageNumberChanged(newPageNum) {
    // Clean up old page first
    if (this.pdfPage) {
      this.pdfPage.destroy();
      this.pdfPage = null;
    }

    // Load new page only after cleanup
    if (this.pdfDoc) {
      this._loadNewPage(newPageNum);
    }
  }

  async _loadNewPage(pageNum) {
    this.pdfPage = await this.pdfDoc.getPage(pageNum);
    // ... your existing rendering logic ...
  }
}

Fix 3: Destroy Old PDF Documents When Switching Files

In your pdf-list-viewer, make sure you destroy the old PDFDocumentProxy before loading a new PDF:

class PdfListViewer extends Polymer.Element {
  static get is() { return 'pdf-list-viewer'; }

  // ... your existing code ...

  async switchToPdf(pdfUrl) {
    // Destroy the old PDF document to free its memory
    if (this.currentPdfDoc) {
      await this.currentPdfDoc.destroy();
      this.currentPdfDoc = null;
    }

    // Load the new PDF
    this.currentPdfDoc = await pdfjsLib.getDocument(pdfUrl).promise;
    this.pageCount = this.currentPdfDoc.numPages;
    // Update iron-list's data source
    this.pages = Array.from({ length: this.pageCount }, (_, i) => i + 1);
  }
}

How to Verify Fixes with Chrome DevTools

To confirm your fixes work:

  1. Take a heap snapshot before switching PDFs
  2. Switch PDFs and browse through pages
  3. Take another heap snapshot and compare
  4. Search for PDFPageProxy or PDFDocumentProxy — you should see old instances being garbage collected instead of piling up

内容的提问来源于stack exchange,提问作者Antonio Dell

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:55:33