回应可能已发生的事件

时间:2011-01-14 02:11:50

标签: actionscript-3 events event-handling

我正在讨论一个非常典型的问题的两种方法:知道事件何时发生或者如果事件已经发生则立即响应它。

在方法一中,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类知识和较少的代码来利用它。当有多个侦听器时,它可能会产生不必要的副作用,因为每次添加侦听器时事件都会触发一次。

第二种方法是可以理解的,也更容易调试,但需要更多的前期工作,似乎打破了Loader的封装。

2 个答案:

答案 0 :(得分:2)

我更喜欢你的第一种方法。我不认为为每个听众添加一个事件是一个问题,但是;事实上,这就是事件机制背后的理念。如果您有N个对象想要在FooEvent发生时收到通知,则每当发生此事件时,您必须为每个对象分派事件。

话虽如此,我不会用addEventListener方法发送事件;我认为那是不必要的副作用,真的。这违背了任何人的合理期望。添加侦听器不应导致事件触发。它应该只是注册一个监听器。您应检查数据是否已加载到加载函数中,并在数据可用时将事件分派到那里(因为此时您的加载操作已完成;而不是在您添加监听器时)。

另一件事:我理解您希望立即发送 。但这有一个问题,这可能是严重的,并导致恼人的,而不是那么明显的错误。如果你立即发送,你基本上有2个接口:一个异步和一个同步。可以在调用代码中正确处理这个问题,但是它需要更多的工作并且它非常容易出错,特别是如果你在某个地方有链接事件(我犯了这种异步/同步加载器的错误而且我学会了这个艰辛的道路)。

它更简单,如果数据立即可用,延迟事件的调度几乎没有区别。只是一个微小的延迟,使处理事件的代码异步运行(setTimeout(dispatchComplete,10)将执行它,在一个不同的堆栈帧中,调用加载器的代码。你会省去一些麻烦,让你的调用代码更简单,我认为这就是你所追求的。

答案 1 :(得分:0)

虽然稍微偏离主题,但我建议你尝试一下信号。这取决于你正在使用什么类型的事件(即鼠标事件仍然需要as3事件,因此在某些情况下它可能需要一些额外的工作),但我发现信号实现起来要干净得多,并且对于自定义事件,这是我的首选。

使用信号我通常设置一个静态var作为主控制器。我发现这比互连的事件监听器和调度器链更好。您可以通过这一个渠道获得驱动您的应用/游戏/网站的所有命令。

我提出这个问题的原因是,如果你走这条路,那么在你有这个事件之前,你基本上都有一个听众。因此,如果在事件发生后创建了一个对象,您可以让它轮询事件是否发生,并且addOnce()函数适用于加载程序和其他预期仅发生一次的事件。所以虽然这不能回答你的问题,但我希望它会增加混乱:)

这里有一个链接,可以让您了解它的工作原理 http://johnlindquist.com/2010/01/21/as3-signals-tutorial/