Passing Functions as Arguments in JavaScript

SquirrelFish.jpg

This morning I had the need of passing a completion function to a JavaScript function - I'm going to be doing an AJAX request, and when that request is done I want this function called. It's pretty obvious, really... when you're doing the request you might want a "Working..." message displayed, and when it's done, you want that removed. So here's the code I ended up with - pretty neat.

The calling function says:

  function showFitData(beg, end) {
    showFitsMessage('Working, please hold on...');
    var url = 'admin?cmd=fitData&out=json';
    // do the request and show the results
    doXMLRequestToTableWithFormat(url, fitTable, fitTableParams,
        function() { clearFitsMessage() });
  }

where we take the JavaScript function and encase it in another function definition. Pretty nice, but not as clean as I actually expected with JavaScript. Here nor there, this works and that's good enough.

The function called looks like this:

  function doXMLRequestToTableWithFormat(url, table, params, doneFcn) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onreadystatechange = function() {
      // if we're not yet done, skip doing anything
      if (xhr.readyState != 4) {
        return;
      }
      // ...otherwise, get the tag for the answer
      var rawJSON = eval('(' + xhr.responseText + ')');
      var answerData = new google.visualization.DataTable(rawJSON);
      // let's get the 'negative as red' formatter for the columns
      var colorFmt = new google.visualization.ColorFormat();
      colorFmt.addRange(null, 0, 'red', null);
      // now let's process each numeric column, in turn
      for (var c = 0; c < answerData.getNumberOfColumns(); ++c) {
        if (answerData.getColumnType(c) == 'number') {
          colorFmt.format(answerData, c);
        }
      }
      // now we can draw it
      table.draw(answerData, params);
      // clean up what we no longer need
      delete answerData;
      delete rawJSON;
      delete colorFmt;
      // if we have a 'done' function, call it
      if ((doneFcn != undefined) && (doneFcn != null)) {
        doneFcn();
      }
  }

With this, it works like a charm. Nice to have worked this out. I'm sure I'll need it again and again.