【问题标题】:Responding to an Event that May Have Already Occurred响应可能已经发生的事件
【发布时间】:2011-01-14 02:11:49
【问题描述】:

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

在方法一中,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 的封装。

【问题讨论】:

    标签: actionscript-3 events event-handling


    【解决方案1】:

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

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

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

    这要简单得多,并且在数据立即可用的情况下延迟事件的调度几乎没有什么区别。只需稍许延迟即可使处理事件的代码异步运行(setTimeout(dispatchComplete,10),在与调用加载程序的代码不同的堆栈帧中。您将为自己省去一些麻烦并使您的调用代码更简单,我认为这就是您所追求的。

    【讨论】:

      【解决方案2】:

      虽然有点离题,但我建议你尝试一下信号。这取决于您使用的是哪种事件(即鼠标事件仍然需要 as3 事件,因此在某些情况下可能需要做一些额外的工作),但我发现信号更易于实现,并且对于自定义活动,是我的首选。

      我通常使用信号设置一个静态变量作为主控制器。我发现这比 Event Listeners 和 Dispatchers 的互连链更好。您可以让驱动您的应用/游戏/网站的所有命令都通过这个漏斗。

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

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

      【讨论】:

        猜你喜欢
        • 2023-03-20
        • 1970-01-01
        • 2012-04-27
        • 2019-06-19
        • 1970-01-01
        • 2011-02-15
        • 2013-06-21
        • 2022-10-13
        • 1970-01-01
        相关资源
        最近更新 更多