TypeError: client.on is not a function 报错排查与修复方法
错误原因
TypeError: client.on is not a function 本质是你调用on()的client对象不是支持事件监听的合法CDP会话实例,具体触发场景:
- 代码里取的
d._client是Puppeteer/Playwright的内部私有属性,下划线开头的属性没有对外兼容性承诺,不同版本里可能指向无事件方法的普通内部对象、undefined,或者被代理过的只读对象,本身就不支持直接绑定事件 - 你监听的
Network.webSocketFrameSent是Chrome DevTools Protocol的协议层事件,只能绑定在官方API创建的CDPSession实例上,不能直接绑在页面对象的内部属性上 - 新版本的Puppeteer/Playwright已经移除了页面对象挂载的
_client属性的事件能力,外部读取到的_client没有继承EventEmitter原型,自然不存在on方法。
修复方案
- 不要读取私有
_client属性,改用官方公开API创建合法CDP会话:- Puppeteer环境:
const client = await DiscordPage.target().createCDPSession() - Playwright环境:
const client = await DiscordPage.context().newCDPSession(DiscordPage)
- Puppeteer环境:
- 绑定网络类事件前,必须先执行
await client.send('Network.enable')开启CDP网络域事件推送,否则绑定后也收不到WebSocket帧数据 - 给回调里的字段加可选链判断,避免字段不存在时抛出额外解析错误。
修正后代码
const DiscordPage = d; await fill_discord(DiscordPage, username, password, email); let client; // 自动适配Puppeteer、Playwright两种运行环境 if (DiscordPage.target) { client = await DiscordPage.target().createCDPSession(); } else { client = await DiscordPage.context().newCDPSession(DiscordPage); } let token; // 先开启网络域监听 await client.send('Network.enable'); client.on('Network.webSocketFrameSent', ({requestId, timestamp, response}) => { try { if (!response?.payloadData) return; const json = JSON.parse(response.payloadData); if(!token && json?.d?.token){ token = json.d.token; write_log(true, `Token: ${token}`); } } catch(e) { // 非JSON格式帧直接忽略 } }) await break_captcha(DiscordPage);
注意事项
- 不要在业务代码里直接调用库的下划线开头内部属性,这类属性会随版本迭代随意调整结构、移除方法,没有任何兼容性保障
- CDP事件是异步触发的,如果需要在
break_captcha执行后读取token值,需要额外加Promise等待逻辑,直接同步读取大概率拿到undefined。
内容的提问来源于stack exchange,提问作者retrocheese
相关产品推荐
相关产品推荐

