给定使用ES6的发布 - 订阅模式如下(从https://davidwalsh.name/pubsub-javascript中提取):
class PubSub {
constructor() {
this.handlers = [];
}
subscribe(event, handler, context) {
if (typeof context === 'undefined') {
context = handler;
}
{
if (this.getHandler(event, handler) == null) {
this.handlers.push({event: event, handler: handler.bind(context), key: Guid()});
}
}
}
unsubscribe(event, handler) {
let filteredHandler = this.getHandler(event, handler);
if (filteredHandler != null) {
let idx = this.handlers.indexOf(filteredHandler);
if (idx > -1) {
this.handlers.splice(idx, 1);
}
}
}
publish(event, args) {
this.handlers.forEach(topic => {
if (topic.event === event) {
topic.handler(args)
}
})
}
getHandler(event, handler) {
if (this.handlers == null || this.handlers.length < 1) {
return null;
}
let filtered = null;
this.handlers.forEach(topic => {
if (topic.event === event && topic.handler === handler) {
filtered = topic;
}
});
return filtered;
}
getNumOfSubsribers() {
if (this.handlers != null && this.handlers.length > 0) {
return this.handlers.length;
}
return 0;
}
}
订阅和发布方法有效。但是,getHandler和unsubscribe方法不能按预期工作(getHandler似乎返回null)。我试图搜索但无法得到满意的解决方案来解决这个问题(不确定绑定到给定上下文的函数如何从数组中过滤掉)。
我在代码中做错了什么?请在getHandler上告诉我,并取消订阅部分代码。
感谢某种帮助。
答案 0 :(得分:2)
这段代码在某些方面很奇怪。
getHandler
不起作用的原因是handler
上推送的对象的handlers
属性不是传入的函数;这是在该函数上调用bind
的结果。格式正确,这是subscribe
:
subscribe(event, handler, context) {
if (typeof context === 'undefined') {
context = handler;
}
{
if (this.getHandler(event, handler) == null) {
this.handlers.push({
event: event,
handler: handler.bind(context), // ** NOTE **
key: Guid()
});
}
}
}
根据定义,该值永远不会等于原始值。
相反,它应该包括原始处理程序,以便稍后检查它。让我们摆脱毫无意义的独立块:
subscribe(event, handler, context) {
if (typeof context === 'undefined') {
context = handler;
}
if (this.getHandler(event, handler) == null) {
this.handlers.push({
event: event,
handler: handler.bind(context),
originalHandler: handler, // ***
key: Guid()
});
}
}
现在,getHandler
可以查找与originalHandler
的匹配项。当我们在那里时,让我们在找到处理程序而不是继续进行时停止循环,并使用语义上合适的Array#find
:
getHandler(event, handler) {
if (this.handlers == null || this.handlers.length < 1) {
return null;
}
let filtered = this.handlers.find(topic => topic.event === event && topic.originalHandler === handler);
return filtered;
}
代码还有其他问题(例如,如果没有提供context
,则将处理程序绑定到自身),但完整的代码审查超出范围;以上是getHandler
不起作用的原因,也就是为什么unsubscribe
不起作用的原因。有了这个修复,unsubscribe
也应该有用(虽然搜索两次似乎很奇怪)。