如何在Puppeteer中安全关闭页面,规避CDP会话崩溃问题?
问题描述
使用Puppeteer创建CDP会话执行滚动手势时,若在滚动操作过程中调用page.close(),程序会崩溃并抛出TargetCloseError,错误信息如下:
node_modules\puppeteer-core\lib\cjs\puppeteer\common\CallbackRegistry.js:73 this._reject(callback, new Errors_js_1.TargetCloseError('Target closed')); ^ TargetCloseError: Protocol error (Input.synthesizeScrollGesture): Target closed at CallbackRegistry.clear
或是另一种错误:
cdp\CDPSession.js:64 return Promise.reject(new Errors_js_1.TargetCloseError(`Protocol error (${method}): Session closed. Most likely the ${this.#targetType} has been closed.`)); ^ TargetCloseError: Protocol error (Network.getCookies): Session closed. Most likely the page has been closed. at CdpCDPSession.send (
核心需求:安全调用page.close(),避免程序崩溃。
解决方案
方案1:等待CDP操作完成后再关闭页面
确保CDP的send操作执行完毕后再关闭页面,从根源上避免会话未完成就被终止的问题:
let browser = await puppeteer.launch(options); const page = await browser.newPage(); const session = await page.target().createCDPSession(); // 等待滚动手势执行完成 await session.send('Input.synthesizeScrollGesture', { x: 100, y: 200, yDistance: -150 }); // 操作完成后关闭页面 await page.close();
方案2:捕获CDP操作的错误(必须中途关闭页面时)
如果业务逻辑要求必须在CDP操作执行过程中关闭页面,直接捕获TargetCloseError即可阻止程序崩溃:
let browser = await puppeteer.launch(options); const page = await browser.newPage(); const session = await page.target().createCDPSession(); // 启动CDP操作,并行处理错误 const scrollPromise = session.send('Input.synthesizeScrollGesture', { x: 100, y: 200, yDistance: -150 }).catch(error => { // 仅忽略目标关闭的错误,其他错误正常抛出 if (error.name !== 'TargetCloseError') throw error; }); // 模拟中途关闭页面 await page.close(); // 等待滚动操作的Promise处理完成 await scrollPromise;
方案3:提前分离CDP会话
在关闭页面之前主动分离CDP会话,切断会话与页面的关联,避免后续错误抛出:
let browser = await puppeteer.launch(options); const page = await browser.newPage(); const session = await page.target().createCDPSession(); // 启动CDP操作 const scrollPromise = session.send('Input.synthesizeScrollGesture', { x: 100, y: 200, yDistance: -150 }); // 主动分离CDP会话 await session.detach(); // 关闭页面 await page.close(); // 处理滚动操作的结果,捕获可能的错误 try { await scrollPromise; } catch (error) { if (error.name !== 'TargetCloseError') throw error; }
内容的提问来源于stack exchange,提问作者C.Unbay
相关产品推荐
相关产品推荐

