How can Node's emitter.removeListener be implemented in ES2015? Adding a callback to an array is easy:
let callbacks = [];
function registerCallback(handler) {
callbacks.push(handler);
});
How can that particular function be removed later, without registerCallback returning some identifier for the function? In other words, unregisterCallback(handler)
should not need any other parameter, and should remove that handler. How would unregisterCallback
check that an anonymous function had been previously added?
Is running handler.toString()
(and potentially a hash function on that) a reliable solution to create an identifier for the function? Or how else should unregisterCallback
iterate through callbacks
to remove that particular element? (Or find the appropriate key in an object or function in a Set.)
mySet.add(function foo() { return 'a'})
mySet.has(function foo() { return 'a'}) // false
答案 0 :(得分:3)
通常的解决方案是将函数本身作为参数传递给unregisterCallback
函数。这就是jQuery所做的事情。
因此unregisterCallback
函数必须使用indexOf
来查找回调索引:
function unregisterCallback(handler) {
var index = callbacks.indexOf(handler);
if (~index) callbacks.splice(index, 1);
}
当然,这意味着用户代码必须保留该功能,它不能是registerCallback
调用中定义的功能。
这不起作用:
registerCallback(function foo() { return 'a'});
// later...
unregisterCallback(function foo() { return 'a'}); // this is a different function
这有效:
function foo(){
return 'a'
}
registerCallback(foo);
// later...
unregisterCallback(foo); // it's the same function
您还可以提供按姓名删除的功能:
// pass either the function or its name
function unregisterCallback(handler) {
var index = -1;
if (typeof handler==="string") {
for (var i=0; i<callbacks.length; i++) {
if (callbacks[i].name===handler) {
index = i;
break;
}
}
} else {
index = callbacks.indexOf(handler);
}
if (~index) callbacks.splice(index, 1);
}
registerCallback(function foo() { return 'a'});
unregisterCallback("foo");
但名称unicity的责任在于用户代码领域,这可能是好的,也可能不是,具体取决于您的应用程序。
答案 1 :(得分:1)
你可以去design,其中事件发射器返回一个可以更新内部状态的可调用对象:
const dispose = sleep.on('sheep', ::sleep.tick)
sleep.once('baanough', dispose)