~ May, 2006 ~

19
May
2006

Dealing with asynchronous events, part 3

I’d like to talk about some improvements to the RPC call mechanisms in Flex 2. Matt Chotin once again proved to me that he knows more about Flex than I will ever know by kindly pointing out that the signature of the RPC calls in Flex 2 have changed to formally return objects of type AsyncToken, which has a built-in responder mechanism.

More »

17
May
2006

Brendan Eich on JavaScript 2

Ajaxian has posted a set of slides from Brendan Eich on the future of JavaScript. As you probably know, we have been tracking the ECMAScript Edition 4 spec very closely in our implementation of ActionScript 3, so many of the concepts will be familiar to you. Because of timing, there are proposals in the new version of the language that are not going into ActionScript 3.

The ones the I’m particularly excited about are:

  • Parametric types (otherwise known as generics)
  • let blocks (removed after more careful reading)
  • yield

Are there any ideas in this slide deck that you would like to see in — dare I say it — ActionScript 4?

16
May
2006

Dealing with asynchronous events, part 2

In the previous entry, I talked about some of the reasons why asynchronous programming can be hard to understand. Now, for some approaches for simplifying things.

Using closures

The first piece of the puzzle is closures. Ely Greenfield (one of the Flex architects) showed me a cool way to use closures to hide some of the complexity of argument passing.

In our last episode, we passed arguments from one part of the code to the next via the call object, like so:

public function getAlbumInfo(albumId: int) : void
{
    // Initiate the call.
    myService.request = { type: "album", albumId: albumId };
    var call : Object = myService.send();

    // Save the albumId for use later.
    call.albumId = albumId;

    // Wire up the handler.
    call.handler = getAlbumInfoResult;
}

public function getAlbumInfoResult(event: Event) : void
{
    // Deal with the results of the previous call.
    var artistId: int = event.result.album.artistId;
    myAlbumList.addAlbum(event.call.albumId, event.result.album);

    // Initiate the next call.
    myService.request = { type: "artist", artistId : artistId };
    var call = myService.send();

    // Save the artistId for use later.
    call.artistId = artistId;

    // Wire up the handler.
    call.handler = getArtistInfoResult;
}

public function getArtistInfoResult(event: Event) : void
{
    // Handle the results of the second call.
    myArtistList.addArtist(event.call.artistId, event.result.artist);
}

If you use closures to handle the argument passing, the code looks like this:

public function getAlbumInfo(albumId: int) : void
{
    var call: Object;

    // Initiate the first call.
    myService.request = { type: "album", albumId: albumId };
    call = myService.send();

    call.handler = function (event: Event) 
    {
        // Handle the results of the first call.
        var artistId: int = event.result.album.artistId;

        // Notice we can use albumId here directly.
        myAlbumList.addAlbum(albumId, event.result.album);

        // Initiate the second call.
        myService.request = { type: "artist", artistId: artistId };
        call = myService.send();

        call.handler = function (event: Event)
        {
            // Handle the results of the second call.
            myArtistList.addArtist(artistId, event.result.artist);
        }
    }
}

This is a bit tricky, so let’s walk through it.

  1. myService.request is set.
  2. The first request is sent.
  3. The callback is stored on the call object for the http request.
  4. Eventually, the result handler is called.
  5. We look up the callback on the call object, and call it.
  6. This causes the first closure to be called.
  7. Inside the first closure, I can access the albumId parameter from the outer function, because that’s how closures work.
  8. Inside of there, a second http request is made.
  9. A new callback is stored on a new call object.
  10. Eventually, the result handler is called.
  11. We look up the callback on the call object, and call it.
  12. This causes closure2 to be called.

So what’s so great about this method? Well, in Ely’s words, “if you squint, it almost looks like you’re not doing asynchronous programming.” You don’t have to register asynchronous event handlers, and you don’t have to do anything too hard to pass arguments around, because of the magic of closures.

More »

16
May
2006

Dealing with asynchronous events, part 1

One of the difficulties in using an asynchronous event model is that it can be difficult to write readable code. This is true of both AJAX applications and Flex applications for the same reason.

I’ve been chipping away at this problem for the past few months, trying various alternatives. I thought it might be helpful to walk through the various coding idioms I tried, as a way of explaining the different approaches.

As an example, let’s take RPC service calls. Let’s say I am using an http service to get information about an album:

public function getAlbumInfo(albumId: int) : void
{
    myService.request = { type: "album", albumId: albumId };
    myService.send();

    // I'd like to do something with the results of
    // my request, but I can't!
}

The problem is that the results don’t come back right away. Code keeps executing and your results might not come for hundreds of milliseconds. Furthermore, the Flash Player does not provide a way to block until the results are ready. In order to respond to the results that eventually come back, you need to trap an event.

public function getAlbumInfo(albumId: int) : void
{
    myService.addEventListener("result", getAlbumInfoResult);       
    myService.request = { type: "album", albumId: albumId };
    myService.send();
}

public function getAlbumInfoResult(event: Event) : void
{
    // Hundreds of milliseconds later, my results
    // have arrived, and I can add them to my list!
    myAlbumList.addAlbum(event.result.album);
}

That’s not so bad, is it? Now, let’s imagine that I need to use the albumId inside the result function. As it turns out, the RPC send() methods have a special object called a call object that lets us do just that.

More »

12
May
2006

More Flex 2 beta 3 migration notes

I’ve just moved a bunch of code over from beta 2 to beta 3, and took notes on some of the migration issues I ran into. The good news is that almost all of them are in the migration doc somewhere.

FWIW, the issues I ran into are:

  • flash.util has been renamed flash.utils
  • Several things have been renamed from hXXX to horizontalXXX.
  • There are times when you have to cast Application.application to DisplayObject
  • DataProvider APIs are no longer on the list classes. For example, you can no longer say myList.getItemAt(index). Instead, say myList.dataProvider.getItemAt(index).
  • ICollectionView.getCursor() has been renamed ICollectionView.createCursor().
  • You no longer have to manually release the iterators you get back from the createCursor() function.
  • The constructor for CollectionEvent now takes an attribute to specify the event type.

This is in addition to the other migration notes I listed here.