【问题标题】:Remove an eventhandler in the handler itself在处理程序本身中删除事件处理程序
【发布时间】:2017-10-04 11:29:14
【问题描述】:

简而言之:我想将 .bind 的结果绑定为它自己的调用中的参数

var bound = foo.bind(this,bound);

因为我不确定如何解决我的问题。

问题:

我有一个依赖于其他项目数组的项目。 删除其中一项后,我想删除依赖项,并删除放置在依赖项上的所有侦听器

我正在努力删除其他依赖项的事件处理程序。我正在尝试使用绑定,但由于处理函数是删除侦听器的函数,我发现我必须将 bind() 调用的结果绑定到它自己的调用中作为参数。这当然行不通。

下面的绑定调用将 'handler' 的未绑定版本绑定为参数,因此 removeEventListener 不起作用,因为它是函数的不同副本。

问题是:我可以使用 bind 来执行此操作和/或如何解决此问题?

我使用的是eventemitter3,但对于任何事件库都应该是一样的。

setHandlers(dependentItem,dependencies)
{
    var handler = this.onDependencyRemoved;
    handler = handler.bind(this,dependentItem,dependencies,handler);//bind itself as third argument
    dependencies.forEach(dependency => {
        dependency.addEventListener("removed",handler);
    });
}
onDependencyRemoved(dependentItem,dependencies,handler)
{
     dependentItem.remove();
     dependencies.forEach(dependency => {
          dependency.removeEventListener("removed",handler);
     });
}

编辑:

在 nodejs 中运行的完整工作示例:

const EventEmitter = require('events');
//const EventEmitter = require('eventemitter3');

class MyEmitter extends EventEmitter {
    remove() {
        console.log("I'm being removed, this should happen only once");
    }
}
var dependent = new MyEmitter();
var dependencies = [new MyEmitter(),new MyEmitter()];

var handler = (e) => removeHandler(dependencies,dependent,handler);

dependencies.forEach(dependency => dependency.once('removed',handler));

var removeHandler = function(dependencies,dependent,handler) {
    //remove the dependent object because one of the dependencies was removed
    dependent.remove();
    //remove the listeners from all of the dependencies
    dependencies.forEach(dependency => {
        console.log('before removing: '+dependency.listeners('removed').length);
        dependency.removeListener('removed',handler);
        console.log('after removing: '+dependency.listeners('removed').length);
    });
}

//should remove the dependent object
dependencies[0].emit("removed");
//should not do anything anymore since the listeners are removed
dependencies[1].emit("removed");

【问题讨论】:

  • 使用 event delegation 并在父元素上添加 一个 处理程序。
  • @Andreas 我在 node.js 中。这些项目是模型/ES6 类实例,而不是 DOM 项目。

标签: javascript node.js function event-handling


【解决方案1】:

你不能使用bind 来做到这一点,但是你可以通过使用闭包来相对容易地做到这一点 - 直接用于要绑定的函数,或者在你自己的类似于bind 的辅助函数中。就这么简单

const handler = (e) => this.onDependencyRemoved(dependentItem, dependencies, handler, e);

我不确定为什么这两个函数是任何东西的方法;它们看起来相当静态。 可能将它们设为dependentItem 的方法是有意义的,在这种情况下,参数甚至整个handler 都不需要存储在闭包变量中,而是可以作为实例属性在构造函数中初始化。

【讨论】:

  • 关闭它仍然不起作用。当我删除事件侦听器时,注册后的处理程序与onDependencyRemoved 使用的处理程序不匹配(===)。我已经使用关闭设置编辑了问题。
  • @Flion 我无法重现,您的代码应该可以工作。我相信您要么没有显示完整的实际代码,要么问题出在其他地方。你能发一个minimal reproducible example吗?我也很好奇您如何检查===使用 addEventListener 保存后处理函数”,因为addEventListener 不会使其存储可用
  • 是的,我只是做了一个最小的完整示例,它与 node.js 本机 EventEmitter 和 eventEmitter3 库都可以正常工作。我意识到并不是所有的时间 removeEventListener 被称为它删除一些东西,因为发出“删除”事件的项目已经删除了它自己的,因为我使用once。 Tnx 的帮助!明天我会赏金。这对我来说是一个重要的问题,我从来不知道一个简单的闭包可以像你展示的那样在它自己的函数中重用一个值。
【解决方案2】:

有其他人提到的更好的方法来解决您的问题。但是,代码还有一个更根本的问题:

var bound = foo.bind(this,bound);

代码中bound 的值在执行时为undefined。这相当于只调用foo.bind(this),这可能不是您想要的。

【讨论】:

  • 我知道这一点,我写它只是为了解释我想要做什么。
猜你喜欢
  • 2010-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
相关资源
最近更新 更多