How It Works: Ajaxian “Guesstimate” on ITunes Counter

Ajaxian “Guesstimate” on Apple Homepage

The Ajaxian blog links to another showcase Ajaxian application: An ITunes Counter on the Apple Homepage. The counter shows the number of songs sold so far. What’s interesting is that the counter redisplays quickly, every 100 milliseconds, but the remote call only occurs once a minute. The counter is continuously updated with a guesstimate that’s good enough for most users, and once a minute has a rendezvous with reality, as the new results come in from the server.

The concept here is cool, because it works for users even though it seems wrong from a technical viewpoint. It’s fine for users because it conveys the general feel of ITunes activity. It goes against the mindset of many programmers because it’s guaranteed to be wrong and, even worse, there’s the possibility the counter will go backwards if the estimate overshoots.

So I’ve added a ”Guesstimate” pattern to the Ajax Patterns. The Apple demo shows how a Guesstimate can be used to enhance the standard ”Periodic Refresh” pattern. I’d be grateful if you can leave a comment on any others you might know of. Javascript-based countdown/expiration is one example I’ve seen, simply using the browser’s timer as a proxy for the server’s timer.

I decided to see how the ITunes counter works, so a walkthrough follows. Fortunately, the code’s really clean and well-commented. Thanks Apple and Dunstan and Dan (who are mentioned in the comments … I think [email protected] was hinting it’s Dunstan Orchard :-)). It’s nice to see a prominent website not obfuscating its Javascript.

Quick Design Overview

The server updates only once every five minutes and the browser checks it once a minute. On each update, the browser gets back the most recent sales figure along with the sales figure five minutes earlier. It knows how many songs have been sold in a five-minute period, so it can work out how many are sold every hundred milliseconds. So it repaints the counter every hundred milliseconds, upping it by that increment.

There are two loops:

  • A quiet loop (doCountdown()) calls the server every minute to get new song stats.
  • A vigorous loop (doCountdown()) uses rate estimation data to morph the counter display every 100 milliseconds.

The key global variables are rate and curCount:

  • rate is the number of songs purchased per millisecond, according to the stats in the XML that’s downloaded each miunte.
  • curCount is the counter value.

So each time the server response comes in, rate is updated to reflect the most recent songs-per-millisecond figure. And curCount is continously incremented according to that figure, with the output shown on the page.

General Observations

  • It’s nice to see a script that’s both well-designed and well-documented. Thanks again!
  • The script is resilient wrt the outputted XML – it doesn’t assume the XML updates every five minutes. It does, however, use [0] and [1] positions to locate current and pre, where it would ideally use the tag attributes. (No biggie, the whole thing’s only a temporary promotion anyway.)
  • Interesting that they’re not using one of the many XMLHttpRequest wrapper frameworks. Rolling your own requests is probably characteristic of most Ajaxian apps right now.
  • The increment-per-millisecond calculations might have been easier if performed on the server-side. I don’t know if the authors had complete control, but the ideal thing would be to output a server-side response containing (a) current count and (b) increment per millisecond. I’m all for heavy use of Javascript when it’s required, but where there’s an app-specific call involved, it may as well take the load off the browser.
  • Every five minutes, the extremely observant (borderline-obsessive) user will notice a sudden jump up as the counter is aligned with reality. It’s almost always “up” because the rate is deliberately adjusted downward a bit, presumably for this exact purpose. The sudden jump up can only happen at the one-minute checkpoints, so the user would have to be staring at the counter for a minute to see it. It would be fun, though pointless, to design the checkpoint re-alignment to be smoother, e.g. a simple algorithm would be to simply predict where the counter should be in one-minute’s time, and base the increment on that figure rather than directly on the current rate. Thus, the adjustment would be amortised over the whole minute.
  • The display can only update at 100 millisecond intervals, so you get a bit of flickering – sometimes an increment, sometimes no change. I could think of two interesting alternatives: (a) Calculate the interval so that it’s roughly the amount of time a single song is sold in. Then, the counter will smoothly flow through each number (until the server-side update occurs), which is what you’d generally expect from a counter. It doesn’t have to be exact because the whole thing’s a guess anyway. (b) Make the delay deliberately large, e.g. two seconds, so people can see how much it’s jumped in that time. But I prefer (a)!


Note that I’ve re-formatted some of it. (Markdown Good, Code+Markdown Bad.)

The page’s initialisation sequence is set up:


So initCountdown() is called first. I wish I could verify this, but apparently the price any Mac user pays for running IE is a static image, while everyone else revels in the Ajaxian counter movement. (I know.)

  if ((browser.isIE == true) && (browser.isMac == true)) {
    var counterDiv = (document.getElementById('counter')) ?
      document.getElementById('counter') : null;
    //Put any chunk of HTML in here you wish to be displayed for IE Mac
    var ieMacContent = '
      <img src="
    counterDiv.innerHTML = ieMacContent;
  } else {

So, for most people, the take-home message is we’re going to run doCountdown() on startup, which is a loop that performs a request, then calls itself a minute later. So it’s performing a request every minute:

//get most recent values from xml and process
//on one minute loop
var refreshTimer = setTimeout(doCountdown,refresh);

If you visit that link, you’ll see the counter XML. This is what will be sent to initializeProcessReqChange once a minute, even though the content is only updated every 5 minutes:

    <count name="curCount" timestamp="Thu, 07 Jul 2005 14:16:00 GMT">
    <count name="preCount" timestamp="Thu, 07 Jul 2005 14:11:00 GMT">

initializeProcessReqChange() does the usual Ajaxian waiting-for-4-and-200-statuses thing, and basically passes the result to setCounters. On first run, it also kicks off runCountdown:

  if (XMLHttpRequests < 1 || !countTimer) runCountdown();

setCounters() parses the XML request. It’s not just looking for the current counter value: by comparing the previous and current values, it’s calculating the all-critical rate variable, a global which tracks number of songs per millisecond.

Let’s walk though the calculation. First, we check if there’s been a new update (remember, the XML is only updating every five minutes at present, but this script is called once a minute). The condition checks if the previous count correspond to what was recently the current count, ie. if the value has “fallen through” to become the previous value, in which case a new current value is reigning:

  preCount = parseInt(req.responseXML.getElementsByTagName('count')[1].
  //if new values
  if (preCount == initCount || initCount == 0) {

Okay, something’s changed. We have the previous count already, now let’s grab everything else we need from the XML:

  initCount = parseInt(req.responseXML.getElementsByTagName
  initDate = new Date(req.responseXML.getElementsByTagName
  preDate = new Date(req.responseXML.getElementsByTagName

Cool, we can then calculate the rate as (number of new songs) / (time elapsed):

  //calculate difference in values
  countDiff = initCount-preCount;
  //calculate difference in time of values
  dateDiff = parseInt(initDate.valueOf()-preDate.valueOf());
  //calculate rate of increase
      ((songs downloaded in previous time)/time)*incr
  rate = countDiff/dateDiff;

Next, an adjustment is applied. The adjustment ensures the guesstimated counter rises a bit slower than we’d expect a real counter to rise. An underguesstimation is a good thing, because it means when we next perform a real update using server-side data, there’s not much chance the counter will drop. In general, we’d expect it to jump up a bit after this alteration, but that’s okay, because it will always do jump one way or the other due to the discrepancy between our guess and reality. The 80% adjustment just about guarantees the jump is northward, which is more in line with user expectations.

  rate = rate*0.8;
      //dunstan adjusting the rate down
      // to 80% as per dan's instructions

What follows is a further adjustment to compensate for the time we’ve spent in this method. I’m surprised it’s necessary, but the net effect anyway is that we have set the global current count value, a tiny bit higher than what was in the XML:

  curCount = initCount+curCountElapsed;

So that’s the calculation that happens when the counter response comes back.

As well as the once-a-minute server call, there’s the once-every-100-milliseconds counter repaint. runCountdown() handles this. Now that we know about the rate variable, it’s quite simple to see what’s going on here. incr is the pause between redisplays – 100ms. So every 100ms, it will simply show the new guesstimate by adding the expected increment in that time.

    //multiply rate by increment
    addCount = rate*incr;
    //add this number to counter
    curCount += addCount;

And finally, morphing the display to show the new guesstimate. Apparently, the show’s over when we hit 500 million downloads, so the counter is only going to show 500 million at that stage.

    c.innerHTML = (curCount<500000000) ?
      intComma(Math.floor(curCount)) : "500,000,000+";

Prototyping Desktop Apps with Ajax?

Tony Darugar on prototyping with Ajax:

[A]s I went to download Tcl/Tk, it occured (sic.) to me that I could use AJAX. All I’m looking for is a simple screen that displays each record in turn. I can slap together the HTML page in no time. I can update the contents of the HTML page by simply slapping the values into javascript variables and eval’ing the result on the browser. Nice and easy.

I’d generally advocate low-tech first and feature-driven design instead of software prototyping. But if you really need a quick and dirty prototype, is Ajax the way to go? If you were demonstrating a complex mathematical algorithm, for instance, I think Ajax is a great way to make it interactive and not have to worry about installing it on the user’s desktops. One of the problems with software prototypes is the installation effort – evaluators need to upgrade upon each cycle, and at a time when installation scripts are usually not in place. That just slows down development – it means prototype reviews get put off and programmers are left wondering what to do next.

The post also highlights a general point about web applications: the zero-install is not just a benefit for end-users, but also speeds the development process, because no time is wasted installing and upgrading on the desktops of all the cameos. Before a serious system goes live, it’s not uncommon – at least in large companies – for it to pass the eyeballs of client representatives, managers, testers, auditors, regulators, sysadmins, one or two generic politicians. If it’s on the web, you can forget about most installation headaches.

Podcast: Testing and JUnit

From the cashing-in-on-ITunes-4.9-hype department, the first podcast in ages.

This time, first of two parts on testing and JUnit. Random apologetic waffle and some announcements at the beginning, main content begins 8 minutes in.

Main thing is, much much less processing and upfront planning so as to just get more of these things out. So if it sounds a bit, err, “spontaneous”, do not adjust your ipod.

Testing and JUnit


Click to download the Podcast. You can also subscribe to the feed if you want future podcasts automatically downloaded - check out the podcast FAQ at

This is a Podcast – a blog entry with an embedded MP3 link. On Internet Explorer, Click the left mouse button to listen, or click the right mouse buttton and “Save As…” to download. Better yet, you can subscribe for updates straight into your PC or ipod – it’s easy, open, and free. Install the free, open-source, Ipodder client and when it starts, just paste this in: “”. Too easy! 15 minutes and you can be subscribed to receive thousands of MP3 podcasts – from official BBC documentaries to business personalities like Sun COO Jonathan Schwartz to scores of amateur publishers speaking about their own interests. They will download straight to your PC as soon as they’re published. You can listen to them on your PC or any portable MP3 player. If you have an IPod, programs like IPodder will push the downloaded MP3s straight into ITunes, so you can leave home each day with new content loaded on to your IPod. More info in the Podcast FAQ.

What Ajax Can’t Do Well (And What Desktop Browsers Should Therefore Exploit)

A while back, I said that Ajax is rich, but not that rich. There’s a lot that Ajax can’t do now and won’t be able to do in the foreseeable future, not in a portable way.

  • Sound support is sketchy and relies on proprietary features as well as plugins
  • On-the-fly graphics generation. (Canvas will soon appear in Firefox, but the same won’t be in IE).
  • Keyboard shortcuts. Yes, keyboard shortcuts, since browser shortcuts take precedence and dominate most of the possible options for single-key and single-key-with-single-modifier. Memo to google: please make a google keyboard with an extra “Ajax” modifier button. (actually, just ditch Caps Lock instead. Hmmm, that gives me an idea …)
  • Local storage for bigger and faster caching, retaining personal data, and so on.
  • Arbitrary connectivity – any protocol to any machine.
  • Listening to OS events, like saving upon shutdown.
  • I’m sure plenty more …

In some senses, Ajax is a threat to desktop applications, so if they weren’t taking full advantage of these facilities before (they weren’t), they will be well served by considering howthey might be useful now. Sound, for instance, still doesn’t get much play. It’s the sense with the second-highest bandwidth and it’s easy for desktop apps to generate, and – newsflash – many people don’t work in open offices so sounds won’t disturb anyone else! As with colour, don’t rely on it – just use it to enhance the experience where it’s feasible.