Promises Promises

The other day at work we needed to re-think the way we were handling asynchronous tasks. In essence, we needed a way to (cleanly!) ensure one task was complete before moving on to the next. Very casually, my boss suggested we implement a ‘Promise’ pattern. Feeling a bit like a fool for having no idea what he meant, I did a bit of Googling and discovered in Actionscript land it’s a very rare concept, so I thought I’d take a bit of time and write about it (mainly to better understand it myself).

Before diving into what promises are, though, I’ll take a look at the problem they solve. What it boils down to is handling asynchronous tasks (such as asset loading, for example) in a clean, intelligent fashion. In the world of Flash and Actionscript, you’ll typically find two strategies for this type of behavior: a ‘bulk loading’ approach, and an ‘event chaining’ approach.

In bulk loading, you’ll usually see a BulkLoader object which gets passed tasks (asset loading tasks typically). It’s usually left up to the BulkLoader to sort out the types of tasks (is it loading an xml file or a png file) and to keep track of when it’s complete. Normally you would see a numLoaded variable increased on every successful load which is then compared to a numToLoad variable. If they are equal, a ‘complete’ event is dispatched. If anything fails along the way, an ‘error’ event is dispatched. This isn’t a bad way to go (I’ve done it more times than I can count), but it has one major drawback: what if you need tasks performed in a very specific sequence and tasks in the middle of the sequence depend on the output of previous tasks (e.g. what if you load an xml or json file and values within it are used to load additional objects)? Now it would be possible to build an intelligent BulkLoader object that performs tasks in the order in which they’re added passing output to input, but that could become an unmanageable mess real quick like.

More often than not, this is where the event chaining approach comes in. Let’s say, for the sake of argument, you’re working on a game and in order for that game to start successfully, it must perform these tasks in this order:

  1. Load graphics (e.g. sprite sheet(s))
  2. Load sounds
  3. Load player info
  4. Load high scores
  5. Initialize the game using all of the above

Only then can the game start and if any of those tasks fail, an error message should be shown and the sequence should start again. Typically, you’ll see a task list like this chained up using ‘onSuccess’ and ‘onError’ callback methods. Something sorta like this:

this.assets.getGraphics(onGraphicsSuccess, onError);
 
private function onError():void
{
	// The sequence has failed. Try again
}
 
private function onGraphicsSuccess(gdo:GameDataObject):void
{
	this.assets.getSounds(onSoundSuccess, onError, gdo);
}
 
private function onSoundSuccess(gdo:GameDataObject):void
{
	this.player.getPlayerInfo(onPlayerInfoSuccess, onError, gdo);
}
 
private function onPlayerInfoSuccess(gdo:GameDataObject):void
{
	this.game.getHighScores(onHighScoreSuccess, onError, gdo);
}
 
private function onHighScoreSuccess(gdo:GameDataObject):void
{
	this.game.init(gdo);
	this.game.start();
}

Again, there is nothing inherently horrible about this approach. Like the bulk loading method, I’ve done it a countless number of times and it always works. As you can see though, as your code base grows, this approach can quickly become unmanageable and messy – especially if you need to add or remove a task from the middle of the sequence.

This is where the ‘Promise’ pattern (or construct or whatever its correct designation may be) comes in. The ‘Promise’ approach takes the above chaining method and codifies it into a neat and readable api. It does so by exposing a ‘then()’ method which accepts your onSuccess and onError callbacks and returns a new Promise object. Using a Promise, the example above can be re-written to look like this:

this.assets.getAssets()
	.then( this.player.getPlayerInfo )
	.then( this.game.getHighScores )
	.then( this.game.init )
	.then( onLoadSequenceComplete, onLoadSequenceError );

Just take a moment to look at how clean and elegant that is. It reads like a simple to-do list. Even a non-coder can see exactly how to add a new task to the middle of that sequence. Now the inner workings of a Promise are slightly more complex, but not much. Essentially when a Promise completes, it should be ‘resolved’ which will automatically call its onSuccess callback. Likewise, should a promise fail, it should be ‘rejected’ which will call its onError callback, which, in turn, should throw an error (a try..catch block within the promise construct will allow you to gracefully handle the thrown error).

And that is really all there is to it.

I know I’ve pretty much just glossed over the usage and explanation here, and there is, obviously, much more to promises, but there are better places for more details, so here’s a quick list:

the best AS3 Promise implementation I’ve come across
a complete example I put together using the above implementation (on Wonderfl)
a good ol’ Wikipedia article
a look at promises in javascript
a very good in depth article

 

2 Comments »

  1. shaun says:

    Promises are fun. BTW, that Deferred implementation I wrote was just a quick port of the CoffeeScript version here:

    https://github.com/CodeCatalyst/promise.coffee

    The original author has also released an AS3 version:

    https://github.com/CodeCatalyst/promise-as3

  2. Devon O. says:

    Hey Shaun,

    Thank you for the comment. And, moreso, thank you for the sharing your AS3 Deferred implementation. I did run across promise-as3 (from the author of promise.coffee) but wasn’t keen on the flex dependencies. I’m sure it wouldn’t have been difficult to remove them, but then I ran across yours and didn’t have to bother. Only thing I still don’t like is that sprite instance hanging out in there for the enterframe tick. In any case we need to write a custom implementation to fit with what we have at work anyway, but your work will be a great starting place, so thanks again.

    d.

RSS feed for comments on this post. / TrackBack URI

Leave a Reply

Devon O. Wolfgang

Technical Reviewer of “The Essential Guide to Flash CS4 AIR Development”

Contributing Author of “Flash AS3 for Interactive Agencies”

Senior Software Engineer at Meez

Starling Particle Editor

boids

Animated Particles, Books, and Code – It’s a New Year


It’s a new year[...]

bug

Logical Or Assignment Bug in ASC2


So, here’s something to keep an eye on if switching to AIR 3.8[...]

Starling Filter Collection

Starling Filter Collection


Building up a collection of filters for the Starling framework[...]

Starling Warp

Warp Filter for Starling


Another filter for the Starling framework[...]

promise

Promises Promises


What it boils down to is handling asynchronous tasks [...] in a clean, intelligent fashion [...]

GodRays

Starling ‘God Ray’ Filter


While cruising the internet today looking for interesting things to try out I ran across this fun little GPU Gem[...]

Alpha in Starling Filters and Basic Branching in AGAL


In plain English to create a circular mask we would want to do something like this[...]

Starling, Nape Physics, and PhysicsEditor


A look at using the PhysicsEditor tool for Nape and Starling [...]

Playing With a Couple Game Ideas


Just a couple game fragments, really[...]

One More Filter For Starling


Another filter for the Starling framework[...]

Filters in Starling


Using and writing filters in the Starling framework[...]

Towards a Better Scratch


Perhaps it was too much Meat Beat Manifesto in the late 80′s [...]

Learning AGAL with AGALMacroAssembler and OpenGL Examples

So the other day I sat down and thought to myself: self, it’s high time you learn you some of this new fancy pants AGAL[...]

UV Scrolling in Starling


Obviously this could come in pretty darned handy for space games, side scrollers, etc, etc[...]

Drawing on Stuff in Away3D 4.0

So, Easter Day, I thought I’d sit down and make a little ‘Paint on an Egg and Send it to Your Friend’ app.

Santabot: A Unity3D Flash Game


All right, so a Christmas game like “Santabot vs. The Flying Saucers from Mars” may be a day late[...]