Thursday, May 6th, 2010

JavaScript asynchronous method queue chaining

Category: Examples, JavaScript

<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?

javascript
< view plain text >
  1. $("<div />")
  2.   .fetch('/server/navigation.html')
  3.   .addClass('column')
  4.   .appendTo('#side');
  5.  
  6. 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:

javascript
< view plain text >
  1. function fetchTweet(url) {
  2.   this.queue = new Queue;
  3.   this.tweet = "";
  4.   var self = this;
  5.   ajax(url, function(resp) {
  6.     self.tweet = resp;
  7.     self.queue.flush(this);
  8.   });
  9. }
  10. fetchTweet.prototype = {
  11.  
  12.   linkify: function() {
  13.     this.queue.add(function(self) {
  14.       self.tweet = self.tweet.replace(/\b@(\w{1,20}\b/g, '<a href="...">$1</a>');
  15.     });
  16.   return this;
  17.   },
  18.  
  19.   filterBadWords: function() {
  20.     this.queue.add(function(self) {
  21.       self.tweet = self.tweet.replace(/\b(****|****|****)\b/g, "");
  22.     });
  23.   return this;
  24.   },
  25.  
  26.   appendTo: function(selector) {
  27.     this.queue.add(function(self) {
  28.       $(self.tweet).appendTo(selector);
  29.     });
  30.   return this;
  31.   }
  32.  
  33. };

Nicely done my friend. Looking forward to more JS goodness inspired from your Twitter work.

Related Content:

Posted by Dion Almaer at 4:41 pm
13 Comments

++++-
4.5 rating from 4 votes

13 Comments »

Comments feed TrackBack URI

Hi, the Dustin Diaz’ twitter account is wrong… http://twitter.com/ded

Comment by graffico — May 6, 2010

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.

Comment by lmorchard — May 6, 2010

Kind of light on error checking, no?

Comment by zachstronaut — May 6, 2010

There should be a “new” before “fetchTweet(url)…” right?

it should be : new fetchTweet(url).linkify().filterBadWords().appendTo(‘#status’);

Comment by fabiomcosta — May 6, 2010

error checking? it’s twitter we’re talking about.

Comment by functionform — May 6, 2010

I worked on something like this for jQuery, here are a few demos.

Comment by Flesler — May 7, 2010

Forgot to say, the demos’ source is meant to be checked to see how is this coded.

Comment by Flesler — May 7, 2010

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!

Comment by genericallyloud — May 7, 2010

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.

Comment by chrismatic — May 7, 2010

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.

Comment by genericallyloud — May 7, 2010

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

Comment by ryanday — May 7, 2010

did a lot of this stuff while at IoMe, really improves your coding skills and how you approach a problem.

Comment by johnantoni — May 10, 2010

This really smells like working with classes.

Comment by icoloma — May 11, 2010

Leave a comment

You must be logged in to post a comment.