使用Puppeteer结合Proxy时出现私有成员读取TypeError如何解决
问题根因
该报错由两个问题共同触发:
- Puppeteer v14及以上版本的Page、Browser实例核心方法,使用ES类私有成员(
#开头的内部属性)做逻辑校验。你用Proxy包装实例后,get捕获器直接返回原始方法时,方法调用的this指向被篡改为Proxy实例,Puppeteer内部校验时发现当前this不是对应类声明的原生实例,直接抛出私有成员访问错误。 - 你当前的get捕获器没有做方法上下文绑定,从page/browser对象上取出的方法脱离原实例调用时,必然丢失正确的
this指向。
排查步骤
- 执行
npm ls puppeteer确认本地安装版本,v14以下版本不会出现这类私有成员校验报错,可快速定位是版本适配问题 - 在Proxy的get捕获器内打日志,访问
goto属性时确认最终返回的是page实例的原生goto方法,没有被customPage、browser上的同名属性覆盖 - 单独脱离page实例调用goto方法做验证:执行
const tmpGoto = page.goto; tmpGoto("http://localhost:3000"),会复现完全一致的报错,可确认是上下文丢失导致的问题
修复方案
修改Proxy的get捕获器逻辑,取到对应属性后,如果是函数类型就绑定回其原本所属的实例上下文,不要直接返回裸方法。修正后的完整代码如下:
const puppeteer = require("puppeteer"); class CustomPage { static async build() { const browser = await puppeteer.launch({ headless: false }); const page = await browser.newPage(); const customPage = new CustomPage(page); const superPage = new Proxy(customPage, { get: function (target, property) { // 按优先级匹配属性,函数类型必须绑定回原实例保证this指向正确 if (customPage.hasOwnProperty(property)) { const val = customPage[property]; return typeof val === 'function' ? val.bind(customPage) : val; } if (browser.hasOwnProperty(property)) { const val = browser[property]; return typeof val === 'function' ? val.bind(browser) : val; } const pageVal = page[property]; return typeof pageVal === 'function' ? pageVal.bind(page) : pageVal; } }); return superPage; } constructor(page) { this.page = page; } } module.exports = CustomPage;
额外注意:调用
goto方法时地址必须带HTTP协议,你测试用例里的localhost:3000要改成http://localhost:3000,否则修复私有成员问题后还会触发无效URL报错。
不要图省事给所有返回值统一绑定Proxy实例作为this,browser和page上的方法绑定到非原生实例上,依然会触发私有成员校验失败。
内容的提问来源于stack exchange,提问作者Pablo Alaniz
相关产品推荐
相关产品推荐

