Once Asynchronous, Always Asynchronous

Oliver Steele writes an excellent blog about coding style,  and has written some good articles on asynchronous communications with a focus on Javascript.

Minimizing Code Paths In Asynchronous Code,  a recent post of his,  is about a lesson that I learned the hard way with GWT that applies to all RIA systems that use asynchronous calls.  His example is the same case I encountered,  where a function might return a value from a cache or might query the server to get the value:   an obvious way to do this in psuedocode is:

function getData(...arguments...,callback) {
   if (... data in cache...) {
      callback(...cached data...);
   }
  cacheCallback=anonymousFunction(...return value...) {
     ... store value in cache...
     callback(...cached data...);
  }
   getDataFromServer(...arguments...,cacheCallback)
}

At first glance this code looks innocuous,  but there’s a major difference between what happens in the cached and uncached case.  In the cached case,  the callback() function gets called before getData() returns — in the uncached case,  the opposite happens.  What happens in this function has a global impact on the execution of the program,  opening up two code paths that complicate concurrency control and introduce bugs that can be frustrating to debug.

This function can be made more reliable if it schedules callback() to run after the thread it is running in completes.  In Javascript,  this can be done with setTimeout().   In Silverlight use System.Windows.Threading.Dispatcher.  to schedule the callback to run in the UI thread.