箭头函数中的 WebSocket 回调未按词法设置“this”
Posted
技术标签:
【中文标题】箭头函数中的 WebSocket 回调未按词法设置“this”【英文标题】:WebSocket callback within arrow function not setting 'this' lexically 【发布时间】:2016-05-07 04:42:35 【问题描述】:我正在尝试在 Angular 2 中创建一个 WebSocket 服务。这是我目前所拥有的:
import Injectable from "angular2/core"
@Injectable()
export class ServerService
public ws:WebSocket;
public myData = ;
constructor()
let ws = new WebSocket('ws://localhost:8080/');
ws.onopen = (event:Event) =>
console.log("Socket has been opened!");
;
ws.onmessage = (event:Event) =>
this.myData = JSON.parse(event.data);
;
;
问题是,当onmessage
运行时,this
关键字变成了WebSocket 对象,而不是我的ServerService
对象。
似乎我的箭头函数正在充当标准函数。这可能是什么原因造成的?还有其他方法可以返回ServerService
对象吗?
【问题讨论】:
您的代码没问题,this
将指向 ServerService。 check the console on this plunk
我认为您正在分配 event.data
类型为 WebSocket
的对象可能就是原因,在 onmessage method
中分配值之前尝试使用控制台
你怎么知道this
关键字变成了web socket对象?
@BingLu 在我调试时这样说。
【参考方案1】:
好的,所以在看到 Abdulrahmans 在 plunk 中工作的示例后,我认为我的环境可能有问题。原来我的 TypeScript 正在编译为 ES5,并且正在输出:
function ServerService()
var _this = this;
this.myData = ;
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function (event)
console.log("Socket has been opened!");
;
ws.onmessage = function (event)
_this.myData = JSON.parse(event.data);
;
我的箭头函数确实被删除了,但被替换为应该(?)在功能上等效的东西。它在 Firefox 中按预期工作,但在 Chrome(我正在调试的地方)中没有。
我将我的 TypeScript 编译器切换为输出 ES6,现在我的 javascript 中有箭头函数,并且我的代码在两个浏览器中都能正常工作。
【讨论】:
你拯救了我的一天。谢谢【参考方案2】:我使用Function.prototype.bind() 修复了它,它仅适用于老式匿名函数,而不是箭头函数。
所以而不是:
ws.onmessage = (event:Event) =>
this.myData = JSON.parse(event.data);
;
我做到了:
ws.onmessage = function(event:Event)
this.myData = JSON.parse(event.data);
.bind(this);
【讨论】:
【参考方案3】:我认为 websocket 在相应实例的上下文中执行了回调(使用call
或apply
方法)。
解决方法包括将 websocket 事件处理程序包装到一个 observable 中:
initializeWebSocket(url)
this.wsObservable = Observable.create((observer) =>
this.ws = new WebSocket(url);
this.ws.onopen = (e) =>
(...)
;
this.ws.onclose = (e) =>
if (e.wasClean)
observer.complete();
else
observer.error(e);
;
this.ws.onerror = (e) =>
observer.error(e);
this.ws.onmessage = (e) =>
observer.next(JSON.parse(e.data));
return () =>
this.ws.close();
;
).share();
这样您就可以使用箭头函数和上下文 this:
this.wsObservable.subscribe(data =>
this.myData = data;
);
有关详细信息,请参阅本文(“基于事件的支持”部分):
https://jaxenter.com/reactive-programming-http-and-angular-2-124560.html【讨论】:
以上是关于箭头函数中的 WebSocket 回调未按词法设置“this”的主要内容,如果未能解决你的问题,请参考以下文章