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

发布于 2024-10-21 05:26:40 字数 566 浏览 1 评论 0原文

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

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

由于我希望我的观察者能够灵活地动态添加和删除需要监视的事件,因此我需要事件对象能够在运行回调后删除自身...例如,如果我的观察者只想对事件做出一次响应,然后不再监视它。

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

我只是好奇是否还有其他人遇到过这个问题并提出了有效的解决方案。

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

预先感谢您的帮助!

I'm trying to write an object relationship that follows an observer pattern where the observer cares about a specific set of events that occur on the subject.

I'm not sure if this is 100% standard, but the way I've constructed it, these event objects are defined within the observer, with custom callbacks that will fire when the event occurs. When an event occurs on the subject, it goes through all it's observers and looks to see who is watching for this event. If it finds observers watching for this event, it triggers the observer event's callback.

Since I want my observers to have the flexibility to add and remove, on the fly, events that care to watch, I need for the event object to have the ability to delete itself after running it's callback... say, for instance, if my observer only wants to respond to an event once, then no longer monitor it.

This seems like a good plan, but I know that a JavaScript object can't have call delete() on itself.

I was just curious is anyone else out there had ran into this and had come up with an effective solution.

My only thought was that I could pass the reference to the parent observer object, to it's child event, then when the callback happens, I could call a method within the parent... something like removeEvent(this) passing the event itself to this function. The removeEvent function could then splice out the event from it's array of events. The only complicated problem would be finding the location of this event object in the array. (taking suggestions on this too, thanks!).

Thanks in advance for the help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

〗斷ホ乔殘χμё〖 2024-10-28 05:26:40

如果您在 removeEvent 方法中传入对事件对象的引用,那么您可以循环遍历所有事件并使用 == 运算符进行测试 - 因为您传入的事件对象是一个引用,与循环中相应的事件对象相比,它将计算为 true,因为它们引用内存中的同一对象。

If you pass in a reference to the event object in your removeEvent method, then you can just loop through all of the events and test with the == operator -- since the event object you passed in is a reference, it will evaluate to true when compared to the corresponding event object in the loop because they reference the same object in memory.

一身软味 2024-10-28 05:26:40

我想我可以尝试回答你的问题,但我不能 100% 确定你是如何实现观察者模式的。也许我下面的代码片段中有一些有用的东西。我假设观察是通过回调函数完成的,并且我对该数据的格式没有任何假设,因此我使用字符串。
我的解决方案的关键是回调接收对主题的引用(这在观察者模式中很常见)。此引用可用于将回调与主题分离。

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

I thought I'd have a go at answering your question but I'm not 100% sure how you've implemented your observer pattern. Perhaps there's something useful in my snippet below. I've assumed that the observation is done via callback functions and I've assumed nothing about the format of that data so I'm using strings.
The crux of my solution is that the callback receives a reference to the Subject (which is usual in the observer pattern). This reference can be used to detach the callback from the 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文