Skip to content

Instantly share code, notes, and snippets.

@cowboy
Created April 14, 2012 15:25
Show Gist options
  • Save cowboy/2385200 to your computer and use it in GitHub Desktop.
Save cowboy/2385200 to your computer and use it in GitHub Desktop.
JavaScript callbackify
/*
* callbackify
*
* Copyright (c) 2012 "Cowboy" Ben Alman
* Licensed under the MIT license.
* http://benalman.com/about/license/
*/
function callbackify(fn, args, done) {
// If the function arity exceeds args length, it's accepts a "done" callback.
var async = fn.length > args.length;
// If the function expects a done callback, add it into the args array.
if (async) { args = args.slice(); args[fn.length - 1] = done; }
// Invoke the function, passing all args, getting its result.
var result = fn.apply(this, args);
// If async, fn will call the done callback.
if (async) { return; }
// Otherwise it has to be called explicitly.
done(result);
}
// This function accepts a callback.
function callbackable(a, b, done) {
done(a + b);
}
// This function returns a value.
function returnable(a, b) {
return a + b;
}
callbackify(callbackable, [1, 2], console.log.bind(console));
// logs 3
callbackify(returnable, [1, 2], console.log.bind(console));
// logs 3
@chapel
Copy link

chapel commented Apr 14, 2012

What about an async function that doesn't specify it's callback in args, and pulls it off the argument stack when run? fn.length isn't fool proof in this sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment