AsyncResult 3/3

Asynchronous Java Script
Asynchronous Java Script

Is this JavaScript serial (killer :)) ever going to finish ? Well I am still having a lot of fun with this little JavaScript mechanism.

For AsyncResult 2/3 please click here.


First of all I have streamlined the AsyncResult itself , and even made it more future proof, by using proper JSON API, and future JSON names. Here is the very latest code:

//
// AsynResult V 8.0
// MIT style (c) 2009-2010 by DBJ.ORG
// caling example
// spawn(
// { 'worker': w1, 
//   'delay': 1000, 
//    'callback': on_async_finished }, 
//   1, 2, 3)
//
// Mandatory arguments :
// 1:single JSON object where
// worker [mandatory] function pointer of the worker 
// to execute asynchronously
// delay [optional] delayed execution time unit in microseconds, 
//  if null then 1.
// callback [optional] called 'back' when worker is done 
//  with AsyncResult instance
// as its only argument
// [optional]
// any arguments required by a worker function
//
function spawn ( ){
var AsyncResult = function(args_) {
var FP = args_[0].worker;
var tu = parseInt(args_[0].tu === null ? 1 : args_[0].tu);
tu = (tu > spawn.maxdelay ? spawn.maxdelay : tu)
var CB = args_[0].callback;
// create properties on the curent instance
this.done = false;
this.retval = null;
this.tid = null;
this.callback = CB;
// preserve the current instance aka 'this' in 'that'
var that = this;
// transform arguments to array and cut the first element
// thus leaving arguments for FP
that.args = Array.prototype.slice.call(args_).slice(1);
// be 'future proof use: http://www.json.org/json2.js
this.toJSONString = function() { return JSON.stringify(that); }
this.toString = function() {
// return JSON formated object exposing private properties
// NOTE: this idiom exposes private properties 
// without get/set methods
return this.toJSONString(); }
// this private method is delay executed *outside* 
// of the context of the current instance
// it is executed in the context of the 'global space' 
// aka the 'window' object
function doit(x) {
try {
// execute FP(args), and preserve its return value
// use 'that' for execution contest
that.retval = FP.apply(that, that.args);
// signal that execution finished ok
that.done = true;
} catch (x) {
// FP() caused an exception
that.retval = x.message;
// for caller to see which one
// signal that execution finished in errror
that.done = false;
}
// for testing purposes show the state of the AsyncResult instance
if (spawn.log) spawn.log("AsyncResult::doit()\n\n" + that);
// use clearInterval to release the timer ID
clearTimeout(that.tid);
// use the callback , if given
if (that.callback) {
var cb_tid = setTimeout(function(x) {
clearTimeout(cb_tid);
// pass 'that'/'this' to the callback
try { that.callback(that);
} catch (x) {
/* ignore callback exceptions, but log them */
if (spawn.log) spawn.log("AsyncResult::doit() callback exception\n\n" 
    + x.message);
}}, 1);
}
}
// delay doit() execution , in the context of the 'window' object
that.tid = setTimeout(doit, tu);
}
return new AsyncResult( arguments ) ; // immediate instance return
} // maximum number of seconds spawn will accept
spawn.maxdelay = 60 * 1000; // is one minute
// assign a logging method. if null will not be used
// otherwise must be a function with a single string argument
spawn.log = null ;

 

Here and now, you might ask yourself a question : “Will I feel lucky, if I use this ?” . After all, ( for you too ) it is sometimes easier to “reinvent a hot water”, than to use other peoples “traps”.

In order to defend and promote my AsyncResult mechanism, I have made one certainly non-trivial example. A famous large-image download mechanism. Here I am actually using a well known jQuery mechanism to do it, but with the “twist”: it is used through my AsyncResult mechanism.

Why? To give more control to you.

How? By giving you one more intermediary event (or step), which happens while browser is waiting for large image to arrive. This you use to show that famous spinning gif, in order to improve “end user experience”.

Can this be done without AsyncResult? Certainly. But in a less encapsulated and less decoupled way.

Here is the testing js FIDDLE for you to try immediately.

For quicker understanding one should really start reading from the end. On calling spawn(), immediately an AsyncResult instance is returned and its toString() method is called, since we are here using it from inside a call to the dbj.log( “…some string …”) method. This is the jist of the software mechanism. Its perceived usage. This is where API succeeds or fails.

/*

*/
dbj.log("Async started, spawn() returned : " +
spawn(
/* first argument is mandatory JSON object */
{ 'worker': begin_async_operation, 
   'delay': 1, 
   'callback': end_async_operation 
 },
/* all the other args are optional. 
  in this case we pass the image source url
  and the callback to be used by jQuery 
  inside load(), on image ready event 
*/
large_image_url,
on_large_image_loaded
)
);

Above, jQuery is extensively used. I hope code is well documented and explained. Enjoy…

 

2 thoughts on “AsyncResult 3/3”

Comments are closed.