Реагирование на событие, которое, возможно, уже произошло - PullRequest
1 голос
/ 14 января 2011

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

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

class MyLoader1 extends EventDispatcher
{
    private var _isComplete:Boolean = false;

    public override function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
    {
        super.addEventListener(type, listener, useCapture, priority, useWeakReference);

        // if the operation is already complete, immediately notify listeners
        if(_isComplete)
        {
            dispatchEvent(new Event(Event.COMPLETE));
        }
    }
}

class Application1()
{
    function main():void
    {
        new MyLoader1().addEventListener(Event.COMPLETE, onComplete);
    }
}

В подходе 2 пользователь MyLoader2 должен сначала проверить состояние завершения MyLoader2, прежде чем решить, следует ли продолжить или добавить прослушиватель, который запускается позже.

class MyLoader2 extends EventDispatcher
{
    private var _isComplete:Boolean = false;

    public function get isComplete():void
    {
        return _isComplete;
    }
}

class Application2()
{
    function main():void
    {
        var loader:MyLoader2 = new MyLoader2();

        if(loader.isComplete)
        {
            // passing null just to simplify the example
            onComplete(null);
        }
        else
        {
            loader.addEventListener(Event.COMPLETE, onComplete);
        }
    }
}

Какие преимущества / недостатки есть у каждого подхода? Есть ли шаблон дизайна, который я мог бы / должен использовать для этой ситуации?

Я склоняюсь к первому, потому что для его использования требуется меньше знаний о классе Loader и меньше кода. Это может потенциально создать нежелательные побочные эффекты, когда есть несколько слушателей, потому что событие будет срабатывать один раз при каждом добавлении слушателя.

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

Ответы [ 2 ]

2 голосов
/ 14 января 2011

Мне больше нравится ваш первый подход. Я не думаю, что отправка одного события для каждого добавленного слушателя является проблемой; на самом деле, это та самая идея, которая стоит за механизмом событий. Если у вас есть N объектов, которые хотят получать уведомления всякий раз, когда происходит FooEvent, вы должны отправлять событие для каждого из них всякий раз, когда происходит это событие.

Сказав это, я бы не отправлял событие в методе addEventListener; Я думаю, что это нежелательный побочный эффект, правда. Это противоречит чьим-либо разумным ожиданиям. Добавление слушателя не должно вызывать событие. Стоит просто зарегистрировать слушателя. Вы должны проверить, загружены ли уже данные в вашу функцию загрузки, и отправить туда событие, если данные доступны (потому что в этот момент операция загрузки была завершена, а не когда вы добавили прослушиватель).

Другое дело: я понимаю, что вы хотите отправить немедленно , если это возможно. Но есть проблема, которая может быть серьезной и приводить к раздражающим и не столь очевидным ошибкам. Если вы отправляете сразу, у вас есть 2 интерфейса: один асинхронный и один синхронный. Это можно правильно обработать в вызывающем коде, но это требует больше работы, и это довольно подвержено ошибкам, особенно если вы где-то цепочками событий (я сделал ошибку из-за такого асинхронного / синхронизирующего загрузчика, и я узнал это трудный путь).

Это намного проще и практически не имеет значения откладывать отправку события, если данные доступны сразу. Просто небольшая задержка, чтобы заставить код, который обрабатывает событие, выполняться асинхронно (setTimeout(dispatchComplete,10) сделает это), в другом кадре стека, который код вызвал загрузчиком. Вы избавите себя от некоторых неприятностей и упростите свой вызывающий код, который, как мне кажется, является тем, к чему вы стремитесь.

0 голосов
/ 14 января 2011

Хоть и немного не по теме, я бы посоветовал попробовать.Это зависит от того, какие события вы используете (т.е. для мышиных событий все еще требуется событие as3, поэтому для некоторых случаев это может быть немного дополнительной работой), но я обнаружил, что сигналы намного чище реализовать и для пользовательскихсобытия, это мой предпочтительный выбор.

используя сигналы, я обычно настраиваю одну статическую переменную, которая действует как главный контроллер.Я считаю, что это лучше, чем взаимосвязанная цепочка прослушивателей и диспетчеров событий.Все эти команды, управляющие вашим приложением / игрой / веб-сайтом, могут проходить через эту воронку.

Причина, по которой я это поднимаю, заключается в том, что если вы идете по этому пути, у вас по сути будет слушатель, прежде чемсобытие.Таким образом, если объект создан после того, как событие произошло, вы можете опросить его на предмет того, произошло ли событие, и функция addOnce() подходит для загрузчиков и других событий, которые, как ожидается, произойдут только один раз.Так что, хотя это не отвечает на ваш вопрос, я надеюсь, что это добавляет путаницы:)

здесь есть ссылка, чтобы дать вам представление о том, как это работает http://johnlindquist.com/2010/01/21/as3-signals-tutorial/

...