Question about observer pattern - JavaScript object removes itself from parent array?

I am trying to write an object relationship that follows an observer pattern, where the observer takes care of a particular set of events that occur on this subject.

I'm not sure that this is a 100% standard, but the way I built it, these event objects are defined in the observer with custom callbacks that will fire when an event occurs. When an event occurs on this issue, it passes through all its observers and watches who watches this event. If he finds observers watching this event, he calls the observer event callback.

Since I want my observers to be able to add and remove, on the fly, the events that need to be watched, I need the event object to be able to delete itself after the callback starts ... let's say for an instance, if my observer only wants to respond to the event once, and then no longer track it.

This seems like a good plan, but I know that the JavaScript object cannot call delete () itself.

I'm just curious that someone else there has come across this and came up with an effective solution.

My only thought was that I could pass a reference to the parent observer object, a child event on it, and then when the callback happens, I could call the method inside the parent ... something like removeEvent(this) passing the event itself to this function. The removeEvent function can then splice an event from this array of events. The only difficult problem is finding the location of this event object in the array. (also accepting suggestions on this subject, thank you!).

Thanks in advance for your help!

+4
source share
2 answers

I thought I would need to answer your question, but I'm not 100% sure how you implemented your observer pattern. Maybe there is something useful in my snippet. I assumed that observation is done through callback functions, and I did not assume anything about the format of this data, so I use strings.
The essence of my decision is that the callback receives a link to the Subject (which is usually in the observer template). This link can be used to detach a callback from an object.

 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 
+2
source

If you pass the reference to the event object to your removeEvent method, you can simply view all the events and test using the == operator - since the event object you passed is a link, it will evaluate to true compared to the corresponding event object in the loop because they refer to the same object in memory.

+4
source

Source: https://habr.com/ru/post/1342927/


All Articles