ES6 - 如何获取特定上下文的数组项(函数)

ES6 - How to get array item (function) of a specific context

给定一个使用 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 向我提出建议,并退订部分代码。

感谢您的帮助。

该代码在几个方面很奇怪。

getHandler不起作用的原因是handlers上推送的对象的handler属性不是传入的函数;这是对该函数调用 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 也应该可以工作(尽管搜索两次似乎很奇怪)。