make-believe.org

The old ticker

For as long as I've been programming, I've argued that the gulf between code and poetry isn't as wide as people think. Recently, confronted with a problem, I decided to develop the solution as a code poem. This is because I am obstreperous.

The problem is one that web developers working with Ajax are beginning to encounter. The chief benefit of Ajax is that it allows communication between browser and server without loading a new page. This is a rather revolutionary development for webheads, representing a marked improvement on earlier methods of remote scripting. But the communication is still (properly) only one-way — the browser can now ask the server for new information, but the server still can't "push" new content to the browser. The browser must initiate all conversations.

This is fine. The way around this is to poll the server for new information using a simple setTimeout or setInterval call. Every now and then, the browser says "Hey server, got anything for me?" and the server either says "Not this time, buddy" or "Sure, here ya go". Now, for a high level of responsiveness in your web application, you may want the browser to ask this question very often, maybe less than once a second for each client.

Well, that's a lot of traffic and a lot of server load. Now consider that, depending on the popularity and ephemerality of your web application content, the number of "Not this time, buddy" responses is going to completely dwarf the number of positive responses from the server. There's got to be a way to minimise all these pointless exchanges.

One way is to replace the constant setTimeout/setInterval calls with a dynamic interval based on the proximity of the last positive response from the server. If the server has just said "Sure, here you go", then obviously the content has recently changed. Maybe someone wrote a comment, maybe they moved a magnet around on a magnetboard, I don't know. The thing is, this activity will in most cases greatly increase the probability of imminent further activity. This is when we want our web application to be at its most responsive. So we pester our server with a rapid succession of "got anything for me?" questions — if the server keeps saying "nope", we'll start reducing the frequency of our pestering.

Enough of the theory. Here's a little poem.

function Heart(pump, rate, highPressure, lowPressure) {
  var heart = this;
  var beat;
  var pulse;

  if (!rate){rate = 1.1;}
  if (!highPressure) {highPressure = 125;}
  if (!lowPressure) {lowPressure = 120000;}

  this.starter = function () {
  if (beat) {clearTimeout(beat);}
    pulse = highPressure;
    timeout = setTimeout(heart.throb, pulse);
  }
  this.throb = function () {
    if (typeof pump == "string") {
      eval(pump);
    } else if (typeof pump == "function") {
      pump();
    } else {
      return;
    }
    heart.pacemaker();
  }
  this.pacemaker = function () {
    if (pulse * rate > lowPressure) {
        pulse = lowPressure;
    } else {
        pulse *= rate;
    }
    beat = setTimeout(heart.throb, pulse);
  }
  heart.starter();
}

The nerdy will note that this is in fact object-oriented JavaScript. The Heart() function is an object. You would create it thus:

    var heart = new Heart(function_to_execute);

If you do that, it will run the function_to_execute function at a steadily decreasing rate: starting at 8 times a second (ie, every 125 milliseconds), but for each call it multiplies the interval until the next call by 1.1. So by the tenth call, for example, the interval is out to 325 milliseconds, or 3 times a second. Eventually, when the interval extends to two minutes, it maintains a constant rate.

Now, if your function_to_execute queries the server using Ajax and gets a positive response, you would simply do this:

    heart.starter();

And it will start peppering the server again at the same declining rate.

The Heart() function takes three additional optional arguments. The first is the heart's rate, which is the constant against which the interval is multiplied. It defaults to 1.1.

The second argument is the heart's highPressure, which is the initial interval (125 milliseconds in the present example). The third argument is the heart's lowPressure — the final interval, the point at which the heart's pulse becomes constant (2 minutes by default).

You can have as many hearts as you like running simultaneously: just create and assign them to different global variables.

Now, I'm aware that in the twenty-first century most people prefer pictures to poetry. So you can click on Jesus to simulate a positive response from his server, the "Maker".

Heartthrobbin' Jesus
Click the Messiah to restart his Immaculate Heart!

Go on, click to your heart's content.

Joseph | 23 Jul 2005

Sorry, comments are not available on this post.

stuff & nonsense

  • Topographic viewTopographic view
     shows elements on a webpage according to how deeply nested they are. It's a bookmarklet for web development.
  • The qualifierThe qualifier
     renders controversial statements on this page harmless. Reinstate the slings and barbs by refreshing. Also a bookmarklet.

  • jjmap
    American Diary

    Two weeks with the apple and the lone star (illustrated).

all posts, ordered by month in reverse-chronological order:

In Words

In Other Words