我正在尝试编写一个遵循观察者模式的对象关系,其中观察者关心主体上发生的特定事件集。
我不确定这是否是100%标准,但是我构建它的方式,这些事件对象是在观察者中定义的,具有在事件发生时将触发的自定义回调。当一个事件发生在主题上时,它会通过它的所有观察者,并查看谁正在观看此事件。如果它发现观察者正在观察此事件,则会触发观察者事件的回调。
由于我希望我的观察者可以灵活地添加和删除需要关注的事件,我需要让事件对象能够在运行它的回调后删除自己...比如,for例如,如果我的观察者只想回复一次事件,那么就不再监视它了。
这似乎是一个很好的计划,但我知道JavaScript对象本身不能调用delete()。
我只是感到好奇的是,其他任何人都碰到了这个并提出了有效的解决方案。
我唯一的想法是我可以将引用传递给父观察者对象,传递给它的子事件,然后当回调发生时,我可以调用父内部的方法...类似于removeEvent(this)
传递事件本身就是这个功能。然后,removeEvent函数可以从它的事件数组中拼出事件。唯一复杂的问题是在数组中找到此事件对象的位置。 (也对此提出建议,谢谢!)。
提前感谢您的帮助!
答案 0 :(得分:4)
如果您在removeEvent
方法中传递对事件对象的引用,那么您可以循环遍历所有事件并使用==
运算符进行测试 - 因为您传递的事件对象in是一个引用,当它与循环中的相应事件对象相比时,它将评估为true,因为它们引用了内存中的相同对象。
答案 1 :(得分:2)
我以为我会回答你的问题,但我并不是100%确定你是如何实现你的观察者模式的。也许在我的下面的代码段中有一些有用的东西。我假设观察是通过回调函数完成的,我没有假设那些数据的格式,所以我正在使用字符串。
我的解决方案的关键是回调接收对Subject的引用(这在观察者模式中是常见的)。此引用可用于从主题中分离回调。
var Subject = {
observers: {},
attach: function( eventType, fn ) {
if( !this.observers[eventType] ) this.observers[eventType] = [];
this.observers[eventType].push( fn );
},
detach: function( fn ) {
var newObservers,
eventType,
i;
for( eventType in this.observers ) {
newObservers = [];
for( i = 0; i < this.observers[eventType].length; i++ ) {
if( this.observers[eventType][i] !== fn ) newObservers.push( this.observers[eventType][i] );
}
this.observers[eventType] = newObservers;
}
},
notify: function( eventType, data ) {
var i, observers = this.observers[eventType].slice(0);
for( i = 0; i < observers.length; i++ ) {
observers[i]( data, this );
}
},
poke: function() {
this.notify( 'testing', 'I got poked' );
}
};
var Observer = {
logEvent: function( data, subject ) {
console.log( 'Every time: ' + data );
},
logEventOnce: function( data, subject ) {
console.log( 'Just once: ' + data );
/*
* THE CRUX
*/
subject.detach( arguments.callee );
}
};
Subject.attach( 'testing', Observer.logEvent );
Subject.attach( 'testing', Observer.logEventOnce );
Subject.poke();
//Every time: I got poked
//Just once: I got poked
Subject.poke();
//Every time: I got poked
Subject.poke();
//Every time: I got poked
Subject.poke();
//Every time: I got poked