Javascript – Adding a callback to a function

javascript

Is there a way to add a callback to any given javascript function without changing its definition? Can this be done without using a library like deferred?

Best Answer

You can make any function have a callback in javascript using the following function:

//takes a function fn, and returns a function that is exactly the same as fn
//except that it also takes a callback as the last argument
//and calls that callback with the return value of fn 
function makeCallbacked(fn){
  return function(){
    var callback = arguments[arguments.length-1];
    var args = Array.prototype.slice.call(arguments, 0, arguments.length-1);
    var result = fn.apply(this, args);
    callback(result);
    return result;
  }
}

Sample in console:

> var test = makeCallbacked(function(a,b){ return a + b });
undefined
> test(1,2,function(result){ console.log("result: "+result); });
result: 3
3   

If you want the callbacks deferred, you can make the slight modification:

//takes a function fn, and returns a function that is exactly the same as fn
//except that it also takes a callback as the last argument
//and defers a call to that callback with the return value of fn
//note that it may take a very long time for the callback to be called 
function makeCallbacked(fn){
  return function(){
    var callback = arguments[arguments.length-1];
    var args = Array.prototype.slice.call(arguments, 0, arguments.length-1);
    var result = fn.apply(this, args);

    setTimeout(function(){
      callback(result);
    }, 0);

    return result;
  }
}

Sample in console:

> var test = makeCallbacked(function(a,b){ return a + b });
undefined
> test(1,2,function(result){ console.log("result: "+result); });
3   
result: 3

Note that this is basically a really stupid thing to write, as you usually want to pass more interesting information to a callback than a return value, and you want the function to probably have better control over when the callback gets called. Just changing the function is probably for the best. It's also a huge waste of resources, if you care about that kind of thing.

Related Topic