ES6类中WebSocket消息接收时方法未定义,无法访问外部上下文
解决WebSocket事件触发时"Cannot read property 'wsHandler' of undefined"的问题
这个报错核心是**this的指向错误**,再加上代码里藏着几个小bug,咱们一步步拆解修复:
1. 先揪出代码里的基础错误
- 构造函数里的
this.ws==null是比较操作,应该改成赋值语句:this.ws = null; intialize拼写错误,正确写法是initialize(少了个字母i)
2. 核心问题:onmessage_recieved里的this指向跑偏了
当你用this.ws.addEventListener('message', this.onmessage_recieved)绑定事件时,事件触发后,onmessage_recieved里的this会指向WebSocket实例本身,而不是你的WebSocketSender对象,自然就找不到wsHandler了。另外你在构造函数里定义的_self是局部变量,外部方法根本访问不到,所以this._self也是undefined。
修复方案有两种,选哪种都能解决问题:
方案一:用箭头函数绑定上下文
把事件监听的回调改成箭头函数,这样this会继承外层的WebSocketSender实例上下文:
this.ws.addEventListener('message', (e) => this.onmessage_recieved(e));
同时修改onmessage_recieved方法,直接用this访问wsHandler:
onmessage_recieved(e) { debugger; let jsonData = JSON.parse(e.data); this.wsHandler.onMessageReceived(jsonData); }
方案二:在构造函数里提前绑定方法的this
在构造函数里把onmessage_recieved的this固定到当前实例:
constructor(wsHandler) { this.wsHandler = wsHandler; this.ws = null; // 修复赋值错误 this.url = ''; // 绑定this指向,确保方法里的this永远指向WebSocketSender实例 this.onmessage_recieved = this.onmessage_recieved.bind(this); }
这样后续添加事件监听时直接写this.ws.addEventListener('message', this.onmessage_recieved)就行,方法里的this不会再跑偏。
3. 完整修复后的代码
class WebSocketSender { constructor(wsHandler) { this.wsHandler = wsHandler; this.ws = null; // 修复赋值错误 this.url = ''; // 方案二的话加上这行绑定: // this.onmessage_recieved = this.onmessage_recieved.bind(this); } initialize(url, sender) { // 修复拼写错误 this.url = url; this.ws = new WebSocket(url); this.ws.onopen = () => console.log("opened"); this.ws.onclose = () => console.log("closed"); this.ws.onerror = () => console.log("error"); // 方案一用箭头函数: this.ws.addEventListener('message', (e) => this.onmessage_recieved(e)); // 方案二直接写: // this.ws.addEventListener('message', this.onmessage_recieved); } send(data) { if (this.ws?.readyState === 1) { // 可选:用可选链避免ws为null时报错 this.ws.send(data); } } onmessage_recieved(e) { debugger; let jsonData = JSON.parse(e.data); this.wsHandler.onMessageReceived(jsonData); } close() { if (this.ws?.readyState === 1) { // 可选:用可选链避免ws为null时报错 this.ws.close(); } } }
额外优化建议
- 在
send和close方法里用可选链this.ws?.readyState,可以避免this.ws还没初始化或者已经关闭时出现额外报错。 - 写代码时多注意拼写细节,像
intialize这种小错误很容易浪费排查时间~
内容的提问来源于stack exchange,提问作者Praveen Kumar N
相关产品推荐
相关产品推荐

