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

Puppeteer Node.js应用读取localStorage与Cookies时遭遇‘Execution context was destroyed’错误的排查求助

解决Puppeteer中"Execution context was destroyed"错误:读取localStorage和Cookies的问题

这个错误的核心原因很明确:当页面发生导航(包括重定向)时,旧页面的执行上下文会被销毁,而你在上下文销毁的时机尝试调用page.evaluate读取localStorage,自然会触发这个报错。咱们来一步步拆解你代码里的问题,然后给出修复方案:

你的代码存在的几个关键问题

  1. 错误的事件触发时机
    你在Network.requestWillBeSent事件里执行page.evaluate和page.cookies——这个事件是在浏览器即将发送请求时触发的,此时旧页面已经开始卸载,执行上下文已经处于销毁过程中,根本无法安全地访问页面内的localStorage。

  2. 冗余的waitForNavigation调用
    page.goto()方法本身就会等待页面导航完成(默认waitUntil: load),之后再调用page.waitForNavigation()会导致代码等待一个不存在的后续导航,大概率会超时,还可能干扰正常的页面流程。

  3. 未处理异步操作的并发问题
    Network.requestWillBeSent事件是同步触发的,但你在里面嵌套了多层异步操作(async/await),这会导致多个异步任务在页面不稳定的状态下并行执行,进一步加剧上下文访问的风险。

  4. 资源泄漏风险
    代码里没有调用browser.close(),每次运行都会残留一个浏览器进程,时间长了会占用大量系统资源。

修复后的代码示例

下面是调整后的代码,解决了上述所有问题:

const dayjs = require('dayjs');
const AdvancedFormat = require('dayjs/plugin/advancedFormat');
dayjs.extend(AdvancedFormat);
const puppeteer = require('puppeteer');
const { config } = require('./config');
const helpers = require('./helpers');
const logs = require('./logs');

const runEmulation = async (body) => {
  logs.debug('starting emulation');
  // vars
  const argOptions = [], journey = [];
  // sandbox config
  if ((config.puppeteer.run_in_sandbox === 'true')) {
    argOptions.push('--no-sandbox');
  }
  // initiate a Puppeteer instance with options and launch
  const browser = await puppeteer.launch({
    args: argOptions,
    headless: (config.puppeteer.run_in_headless === 'true') ? true : false
  });
  // launch a new page
  const page = await browser.newPage();
  
  // 设置用户代理
  await page.setUserAgent(body.userAgent);

  // 监听页面导航完成事件——此时新页面的执行上下文已经完全就绪
  page.on('framenavigated', async (frame) => {
    // 只处理主框架的导航,忽略子框架
    if (!frame.parentFrame()) {
      try {
        // 简化localStorage读取逻辑
        const localStorageData = await page.evaluate(() => {
          return Object.entries(localStorage).map(([key, value]) => ({ key, value }));
        });
        // 读取Cookies
        const cookies = await page.cookies();
        
        journey.push({
          url: frame.url(),
          type: 'Page Load',
          storage: {
            cookies: cookies ?? [],
            local: localStorageData ?? []
          },
          duration_in_ms: 0,
          duration_in_sec: 0,
          loaded_at: dayjs().valueOf()
        });
      } catch (err) {
        logs.error(`Failed to scrape storage data: ${err.message}`);
      }
    }
  });

  // 导航到目标URL,等待网络空闲确保页面完全加载
  await page.goto(body.url, { waitUntil: 'networkidle2' });

  console.log(journey);
  
  // 关闭浏览器,释放资源
  await browser.close();
}

exports.runEmulation = runEmulation;

关键修复点说明

  • 改用framenavigated事件:这个事件在页面导航完全完成后触发,新的执行上下文已经创建完成,此时访问localStorage和Cookies是绝对安全的。
  • 过滤主框架:通过!frame.parentFrame()确保我们只处理主页面的导航,避免子框架的无关操作干扰数据收集。
  • 添加错误捕获:用try/catch包裹存储读取操作,避免单个页面的读取失败导致整个程序崩溃。
  • 优化localStorage读取:用Object.entries替代手动循环,代码更简洁高效。
  • 清理资源:添加browser.close(),避免浏览器进程残留导致的资源泄漏。
  • 明确导航等待策略:设置waitUntil: 'networkidle2',确保页面加载完成后再继续后续逻辑,比默认的load更可靠。

内容的提问来源于stack exchange,提问作者Ryan H

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 03:07:36