Extending ActionScript classes to provide AsyncToken like behavior

When you use a class from the Flex framework that does an asynchronous call, you can use the AsyncToken that the call returns to save values/objects that you need when the result event is triggered.

Let’s look at this code:

private function getData():void {
    //create a new HTTPService
    var myService = new HTTPService();
    //add event listener for result
    myService.addEventListener(ResultEvent.RESULT, resultListener);
    //save the async token
    var token:AsyncToken = myService.send();
    //add to token our own data
    token.myData = {name: "john doe", id : 1};
}

private function resultListener(event:ResultEvent):void {
    //retrieve from event.token our data
    myData:Object = event.token.myData;
}

So, we have two functions. The first, getData() creates a HTTPService, attaches an event listener for the result event, and then makes a call to the server. When it makes a call, an AsyncToken is returned. I can use this token to store some info I need in the result listener. The second function is the definition of the result listener. When this function is called, you can access the AsyncToken from the property token from event: event.token. Having the token, it is easy to retrieve the data that I stored when I made the call to the service.

Why is that useful? Sometimes you want to be able to associated some data to a particular call, so when result event is called, you are able to take a different actions based on the data passed.

Unfortunately, when you do a call to a class from Flash, for example, flash.net.URLLoader you don’t have this AsyncToken returned. Consider the following code:

var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, completeListener);
//this line does not working; the load() method is not returning anything
var token = loader.load(new URLRequest("http://mysite/pic.png));

How do you pass your data between the call and the result for objects that are not using AsyncToken? One simple way is to extend the object you want to use, and add one property to store an object. Let’s do this for the URLLoader class:

public class MyLoader extends URLLoader {

    private var _data:Object;

    public function MyLoader(data:Object) {
        super();
        this._data = data;
    }

    public function get data():Object {
        return this._data;
    }
}

Now, let’s see how you can use this object to do asynchronous calls and still be able to pass data:

var myData:Object = {name : "john doe", id : 9};
var loader:MyLoader = new MyLoader(myData);
loader.addEventListener(Event.COMPLETE, completeListener);
//make a request for an item from server
loader.load(new URLRequest("http://myste/pic.png));

//complete listener for loader
private function completeListener(event:Event):void {
    //retrieve the loader instance
    var myLoader:MyLoader = event.target;
    //retrieve the data object
    var myData:Object = myLoader.data;
}

When I create the custom loader object, I pass a reference to the data object that I want to retrieve when the loader has the response (this object is stored using the _data property from MyLoader). When the complete event is reached, using the target property on the event object, I retrieve the MyLoader object that made the call . Having the loader object, I can access the data property to retrieve the original data I stored.

4 thoughts on “Extending ActionScript classes to provide AsyncToken like behavior

  1. Wouldn’t you have a problem if you used the same loader to make more than one async call given that it is possible that a second request could be sent before the first response comes back? Since the token is just being stored in the loader, any subsequent call would overwrite the previous value making it impossible to “link” the data to its request.

    I think the AsyncToken in flex does not have that issue.

  2. @Rob McKeown

    Good point.
    Indeed, I would have a problem in this case. So, the way you should use MyLoader for multiple calls is to instantiate for each call if you plan to do multiple calls one after another.

Leave a Reply

Your email address will not be published. Required fields are marked *