Thursday, May 6th, 2010
JavaScript asynchronous method queue chaining
<p>
"Guess who's back? Back again....."
The JavaScript slim shady himself.... Dustin Diaz (formerly of YUI - Google, now of Twitter) has taken some time out for his busy coding at Twitter, and photography awesomeness to get back to some JS blogging.
Dustin has written up a pattern that he used in Twitter @anywhere, the asynchronous method queue chaining pattern:
One technique you don’t often see is queueing up a chain of methods, asynchronously, by which functions can be linked together independent of a callback.
Let's start with the end result. What if you could do this?
-
-
$("<div />")
-
.fetch('/server/navigation.html')
-
.addClass('column')
-
.appendTo('#side');
-
-
fetchTweet(url).linkify().filterBadWords().appendTo('#status');
-
You grab content, tweak style, and change the DOM, all in a single chain. Or, fetch a tweet, add href, filter it, and then change the DOM.
Here is an example that does this.
The internals of the Twitter example become:
-
-
function fetchTweet(url) {
-
this.queue = new Queue;
-
this.tweet = "";
-
var self = this;
-
ajax(url, function(resp) {
-
self.tweet = resp;
-
self.queue.flush(this);
-
});
-
}
-
fetchTweet.prototype = {
-
-
linkify: function() {
-
this.queue.add(function(self) {
-
self.tweet = self.tweet.replace(/b@(w{1,20}b/g, '<a href="...">$1</a>');
-
});
-
return this;
-
},
-
-
filterBadWords: function() {
-
this.queue.add(function(self) {
-
self.tweet = self.tweet.replace(/b(****|****|****)b/g, "");
-
});
-
return this;
-
},
-
-
appendTo: function(selector) {
-
this.queue.add(function(self) {
-
$(self.tweet).appendTo(selector);
-
});
-
return this;
-
}
-
-
};
-
Nicely done my friend. Looking forward to more JS goodness inspired from your Twitter work.







Hi, the Dustin Diaz’ twitter account is wrong… http://twitter.com/ded
I keep meaning to blog about this, but I’ve been playing with a bit of async method queue chaining of my own in developing webOS apps:
http://github.com/lmorchard/weave-webos/blob/master/src/javascripts/Decafbad/Chain.js
http://github.com/lmorchard/weave-webos/blob/master/src/tests/Weave/Service_Tests.js#L137
This is a bit different than what Dustin’s doing, but I’ve found it handy.
Kind of light on error checking, no?
There should be a “new” before “fetchTweet(url)…” right?
it should be : new fetchTweet(url).linkify().filterBadWords().appendTo(‘#status’);
error checking? it’s twitter we’re talking about.
I worked on something like this for jQuery, here are a few demos.
Forgot to say, the demos’ source is meant to be checked to see how is this coded.
Method chaining is nice, but I’ve been using a mechanism like this for a few years now, and I’ve found what is even better (for a large app anyway) is the ability to pass these queues around. Call an asynchronous function, get back a queue. Pass the queue to another asynchronous function, and that function will run on the queue you pass it. It really allows for some very complex function composition. Couldn’t live without it!
I’ve been playing around with something like this for a little while. I’m much more impressed by the refinement of this pattern that genericallyloud is discussing.
The major difference between Dustin’s implementation and mine is that his has a simpler, more narrow focus – start with an asynchronous call, pile up some callbacks and then execute them when complete. What I do with mine is more like a poor man’s continuation. You add callbacks to it in a similar way, but instead of having a single flush, you can start or stop it. So you would stop it before you make an asynchronous call, and then restart it when the asynch call is complete.
Using this basic approach, you can easily do a lot of crazy things like perform many asynchronous calls in a row in order across many different function calls that know nothing about each other. With some more work, I can do things like join queues so that one will wait for the other to complete, build in error handling in case of an error on the queue, add interrupts so that you can insert into the queue while running on the queue, etc.
If I could open source the code, I would, but I’ll just say that there are a lot of possibilities out there using this technique.
hey guys for fun i extended Dustins example to support full async chain support for jquery and qany other object that can be reflected. ie any obejct!
http://ryanday.org/jq.php
i added $.asyncSelect as the core and $.fn.appendAndSelect as example jquery plugin functions
git hug gist here
http://gist.github.com/393836
i have 2 tests for object reflection and queuing one for a basic object and another for jquery
did a lot of this stuff while at IoMe, really improves your coding skills and how you approach a problem.
This really smells like working with classes.