开发者

Responding to an Event that May Have Already Occurred

I'm debating two approaches to a pretty typical problem: Knowing when an event occurs or responding to it immediately if it already HAS occurred.

In approach one, a user of MyLoader1 adds an event listener which will be fired immediately if the loader is already complete.

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);
    }
}

In approach 2, a user of MyLoader2 must first check the completion status of MyLoader2 before deciding whether to proceed or add a listener, which is fired later.

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);
        }
    }
}

What advantages/disadvantages are there to each approach? Is there a design pattern out there that I could/should be using for this situation?

I'm leaning towards the first because it requires less knowledge of the Loader class and less code to leverage it. It could potentially create unwanted side effects when there are multiple listeners though, because the event will fire once for each time a listener is added.

The second method is understandable and easier to debug, but requires more up front work and seems to break encapsulation of the Loader.


I like your first approach better. I don't think that dispatching one event for each listener added is a problem, though; in fact, that's the very idea behind the event mechanism. If you have N objects that want to be notified whenever FooEvent occurs, you have to dispatch the event for each one whenever this event takes place.

Having said that, I wouldn't dispatch the event in the addEventListener method; I think that's the unwanted side effect, really. It goes against anyone's reasonable expectations. Adding a listener should not cause the event to fire. It should just register a listener. You should check whether the data is already loaded in your load function and dispatch the event there if the data is available (because at that point your load operation completed; not when you added the listener).

Another thing: I understand that you want to dispatch immediately if possible. But this has a problem, that can be serious and lead to annoying and not so obvious bugs. If you dispatch immediately you basically have 2 interfaces: one asynchronous and one synchronous. It's possible to handle this correctly in the calling code, but it requires more work and it's quite error prone, especially if you have chained events somewhere (I've made the error of having this kind of async/sync loader and I learned this the hard way).

It's much simpler and it makes almost no difference to delay the dispatching of the event in case the data is available right away. Just a tiny delay to make the code that handles the event run asynchronously (setTimeout(dispatchComplete,10) will do it), in a different stack frame that the code that called the loader. You'll save yourself some troubles and make your calling code simpler, which I think is what you're after.


Though slightly off topic, I would suggest you give signals a try. It depends on what kind of events you are using (ie. Mouse Events would still require the as3 Event so for some instances it might be a bit of extra work), but I've found signals a lot cleaner to implement, and for custom events, it is my preferred choice.

using a signals I usually set up one static var that acts as the main controller. I find this is better than the interconnected chain of Event Listeners and Dispatchers. You could have all the commands driving your app/game/website going through this one funnel.

The reason I'm bringing this up is that if you go this route, you essentially have a listener before you have the event. So if an object is created after the event has taken place, you could have it poll for whether an event occoured, and the addOnce() function is good for loaders and other events that are expected to happen once only. So while this does not answer your question, I hope it adds to the confusion :)

there's a link here to give you an idea of how it works http://johnlindquist.com/2010/01/21/as3-signals-tutorial/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜