观察者模式问题 - JavaScript对象从父数组中删除自身?

时间:2011-03-09 01:38:20

标签: javascript arrays object parent observer-pattern

我正在尝试编写一个遵循观察者模式的对象关系,其中观察者关心主体上发生的特定事件集。

我不确定这是否是100%标准,但是我构建它的方式,这些事件对象是在观察者中定义的,具有在事件发生时将触发的自定义回调。当一个事件发生在主题上时,它会通过它的所有观察者,并查看谁正在观看此事件。如果它发现观察者正在观察此事件,则会触发观察者事件的回调。

由于我希望我的观察者可以灵活地添加和删除需要关注的事件,我需要让事件对象能够在运行它的回调后删除自己...比如,for例如,如果我的观察者只想回复一次事件,那么就不再监视它了。

这似乎是一个很好的计划,但我知道JavaScript对象本身不能调用delete()。

我只是感到好奇的是,其他任何人都碰到了这个并提出了有效的解决方案。

我唯一的想法是我可以将引用传递给父观察者对象,传递给它的子事件,然后当回调发生时,我可以调用父内部的方法...类似于removeEvent(this)传递事件本身就是这个功能。然后,removeEvent函数可以从它的事件数组中拼出事件。唯一复杂的问题是在数组中找到此事件对象的位置。 (也对此提出建议,谢谢!)。

提前感谢您的帮助!

2 个答案:

答案 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