Javascript Workers: An Ajax Example With Callback

I was browsing the Internet one day looking for a conference I could possibly attend regarding web technologies. I came across a certain conference that caught my eye which talked about Javascript workers. To be honest, I’ve never used workers or had any experience with multi-threaded web programming, but, after understanding how they work, I can certainly see the benefit. Describing Javascript workers is beyond the scope of the post, but you can get more information from here and here. In a nutshell, however, Javascript workers allow you to multi-thread your application. This would be nice if, for example, you have several AJAX calls that you need to do and you don’t want the calls to affect the UI in any way (i.e. freezing).

So…I thought it’d be neat to have a sort of practical example for a Javascript worker. In this short example, I’ll show how you can access a web service via a worker. The web service that I used is from openweathermap.org. In this instance, I do a simple call to figure out what the weather is given a city.

worker.js:

addEventListener('message', function (oEvent) {
  var ajax = function (url, callback) {
    var request_o = null;
    try {
      request_o = new XDomainRequest();
    }
    catch(ex) {
      try {
        request_o = new XMLHttpRequest();
      }
      catch(ex) {
        request_o = false
      };
    };
    if(request_o)  {
      if(request_o.toString().indexOf('XDomainRequest') < 0) {
        request_o.onreadystatechange = function () {
          if(request_o.readyState == 4) {
            callback.apply(this, [request_o.responseText, request_o.status, request_o]);
          }
        };
      }
      else {
        request_o.onload = function () {
          callback.apply(this, [request_o.responseText, request_o.status, request_o]);
        };
      };
      request_o.open("GET", url);
      request_o.send(null);
    };
  };
  ajax('http://api.openweathermap.org/data/2.5/weather?q=' + escape(oEvent.data.in) + '&units=metric', function (out) {
    postMessage({id: oEvent.data.id, out: JSON.parse(out)});
  });
});

index.html:

var factory = (function () {
  var tasks = {}, i = 0, worker = new Worker("worker.js");

  worker.addEventListener('message', function (oEvent) {
    if (tasks[oEvent.data.id]) { tasks[oEvent.data.id](oEvent.data.out); }
    delete tasks[oEvent.data.id];
  });

  return function (data, callback) {
    tasks['task-' + i] = callback || function () {};
    worker.postMessage({
      id: 'task-' + (i++),
      in: data
    });
  };
})();

var handler = function (out) {
  console.log(out.weather[0].description + ' in ' + out.name + ' and the temperature is currently ' + out.main.temp + '°C.');
};
factory('Washington, DC', handler);
factory('Miami, FL', handler);
factory('London, UK', handler);
factory('Manila, Philippines', handler);
factory('San Francisco, CA', handler);
factory('Rome, Italy', handler);
factory('Sydney, Australia', handler);
factory('Toronto, Canada', handler);
factory('Paris, France', handler);
factory('Honolulu, HI', handler);

Output:

broken clouds in Miami and the temperature is currently 25.33°C.
sky is clear in Washington and the temperature is currently 1.02°C.
few clouds in London and the temperature is currently 3.97°C.
mist in San Francisco and the temperature is currently 15.48°C.
few clouds in Manila and the temperature is currently 24°C.
scattered clouds in Rome and the temperature is currently 8.5°C.
light intensity drizzle in Sydney and the temperature is currently 19°C.
proximity shower rain in Toronto and the temperature is currently -14.22°C.
broken clouds in Paris and the temperature is currently 5.21°C.
sky is clear in Honolulu and the temperature is currently 24.51°C.