Вопрос шаблона наблюдателя - JavaScript Object удаляет себя из родительского массива? - PullRequest
4 голосов
/ 09 марта 2011

Я пытаюсь написать объектные отношения, которые следуют шаблону наблюдателя, где наблюдатель заботится об определенном наборе событий, которые происходят на предмете.

Я не уверен, является ли это 100% -ным стандартом, но, как я его построил, эти объекты событий определены внутри наблюдателя с пользовательскими обратными вызовами, которые будут срабатывать при возникновении события.Когда на объекте происходит событие, оно проходит через всех своих наблюдателей и смотрит, кто смотрит за этим событием.Если он обнаруживает наблюдателей, наблюдающих за этим событием, он запускает обратный вызов события наблюдателя.

Поскольку я хочу, чтобы мои наблюдатели имели возможность гибко добавлять и удалять на лету события, которые нужно наблюдать, мне нужно дляу объекта события есть возможность удалить себя после выполнения своего обратного вызова ... скажем, например, если мой наблюдатель хочет ответить на событие только один раз, он больше не отслеживает его.

Это похоже на хороший план, но я знаю, что объект JavaScript не может иметь вызов delete () сам по себе.

Мне было просто любопытно, кто-нибудь еще сталкивался с этими придумал эффективное решение.

Моя единственная мысль состояла в том, чтобы я мог передать ссылку на родительский объект-наблюдатель, на его дочернее событие, затем, когда произойдет обратный вызов, я мог бы вызвать метод внутри родительского объекта ... что-то вроде removeEvent(this)само событие для этой функции.Затем функция removeEvent может склеить событие из своего массива событий.Единственная сложная проблема - найти местоположение этого объекта события в массиве.(принимая предложения и по этому поводу, спасибо!).

Заранее спасибо за помощь!

Ответы [ 2 ]

4 голосов
/ 09 марта 2011

Если вы передадите ссылку на объект события в вашем методе removeEvent, то вы можете просто пройтись по всем событиям и протестировать с помощью оператора == - поскольку переданный вами объект события является ссылкой, он будет иметь значение true при сравнении с соответствующим объектом события в цикле, поскольку они ссылаются на один и тот же объект в памяти.

2 голосов
/ 09 марта 2011

Я подумал, что смогу ответить на ваш вопрос, но я не уверен на 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
...