TypeScript强类型事件包绑定后无法取消订阅的解决方案咨询
解决强类型事件包中bind导致取消订阅失效的问题
这问题我之前在项目里也踩过坑!bind确实能解决this指向,但因为每次调用bind都会生成一个全新的函数实例,导致你取消订阅时传的函数和之前订阅的不是同一个引用,自然没法匹配成功。给你几个靠谱的解决方案:
方案1:用类箭头函数属性自动绑定this
把Component里的Update方法改成类箭头函数属性,这样this会自动绑定到Component实例,而且函数引用是固定的,订阅和取消都能正常工作:
let onUpdate = new SignalDispatcher(); let component = new Component(); // 直接订阅,无需bind onUpdate.sub(component.Update); // 取消订阅也直接用原引用 onUpdate.unsub(component.Update); void Update(){ this.onUpdate.dispatch(); } class Component { // 改成箭头函数属性,this自动绑定实例 public Update = () => { // do stuff,这里this肯定是Component实例 console.log(this); } }
这个方案最省心,不需要额外管理引用,适合你能修改Component类的场景。
方案2:手动保存绑定后的函数引用
如果没法修改Component类的写法,那就在订阅时把绑定后的函数存起来,取消订阅时用这个保存的引用:
let onUpdate = new SignalDispatcher(); let component = new Component(); // 保存绑定后的函数引用 const boundUpdateHandler = component.Update.bind(component); onUpdate.sub(boundUpdateHandler); // 取消订阅时用这个保存的引用 onUpdate.unsub(boundUpdateHandler); void Update(){ this.onUpdate.dispatch(); } class Component { public Update(){ // do stuff,this现在指向Component实例 console.log(this); } }
注意一定要保留好boundUpdateHandler的引用,要是丢失了就没法取消订阅了。
方案3:利用事件库的上下文参数(如果支持)
很多强类型事件库的订阅方法会支持传入第二个参数作为this上下文,比如这个strongly typed events包的sub方法可能有这样的重载:
// 假设库支持这种写法,直接传方法和上下文 onUpdate.sub(component.Update, component);
这样库内部会帮你处理this绑定,而且取消订阅时直接传component.Update就能匹配,因为库会关联方法和上下文来做比对。你可以查一下这个包的文档确认下有没有这个功能,有的话这也是个很优雅的解决方案。
总结一下,优先用方案1,简单不折腾;如果不能改类就用方案2;要是库支持上下文参数就用方案3,都能解决你遇到的this指向和取消订阅的问题。
内容的提问来源于stack exchange,提问作者jessey stend
相关产品推荐
相关产品推荐

