Created
November 8, 2011 07:17
-
-
Save ahamid/1347206 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Allows for calling a method asynchronously and queueing pending callbacks to avoid | |
* race conditions. | |
* | |
* Example: | |
* | |
* function createUniverse(arg, callback) { | |
* // important stuff that should not run in parallel here | |
* callback(whatever); | |
* } | |
* | |
* You can now safely run this with queued callbacks: | |
* | |
* // or use bind/curry | |
* function inflationary(cb) { createUniverse("inflationary", cb); } | |
* | |
* multiplexCallback(inflationary, function() { ... thing one ... }); | |
* multiplexCallback(inflationary, function() { ... thing two ... }); | |
* multiplexCallback(inflationary, function() { ... thing three ... }); | |
*/ | |
function multiplexCallback(callbackable, callback) { | |
if (!callbackable.__multiplex_callback_list) { | |
callbackable.__multiplex_callback_list = []; | |
callbackable.__multiplex_callback_list.push(callback); | |
callbackable(function () { | |
for (var i = 0, l = callbackable.__multiplex_callback_list.length; i < l; i++) { | |
callbackable.__multiplex_callback_list[i](); | |
} | |
// delete processed callbacks | |
delete callbackable.__multiplex_callback_list; | |
}); | |
} else { | |
callbackable.__multiplex_callback_list.push(callback); | |
} | |
} | |
function makeMultiplexedCallbackable(callbackable) { | |
return function(callback) { | |
return multiplexCallback(callbackable, callback); | |
} | |
} | |
describe("#multiplexedCallback", function() { | |
it("it should invoke all callbacks after asynchronous invocation", function() { | |
var times_called = { | |
red: 0, | |
green: 0 | |
}; | |
function paint_bikeshed(color, callback) { | |
// pretend important async stuff is here | |
times_called[color] = times_called[color] + 1; | |
setTimeout(callback, 1000); | |
} | |
var red_one = ""; | |
var red_two = ""; | |
var red_three = ""; | |
var red_done = false; | |
var red_callbackable = makeMultiplexedCallbackable(function(cb) { paint_bikeshed("red", cb); }); | |
var green_one = ""; | |
var green_two = ""; | |
var green_three = ""; | |
var green_done = false; | |
var green_callbackable = makeMultiplexedCallbackable(function(cb) { paint_bikeshed("green", cb); }); | |
runs(function() { | |
red_callbackable(function() { red_one = "red: sanding"; }); | |
red_callbackable(function() { red_two = "red: priming"; }); | |
red_callbackable(function() { red_three = "red: painting"; red_done = true; }); | |
green_callbackable(function() { green_one = "green: sanding"; }); | |
green_callbackable(function() { green_two = "green: priming"; }); | |
green_callbackable(function() { green_three = "green: painting"; green_done = true; }); | |
}); | |
this.waitsFor(function() { | |
return red_done && green_done; | |
}, 20000); | |
runs(function() { | |
// method only called once, but all callbacks are called afterwards! | |
expect(times_called.red).toEqual(1); | |
expect(red_one).toEqual("red: sanding"); | |
expect(red_two).toEqual("red: priming"); | |
expect(red_three).toEqual("red: painting"); | |
// method only called once, but all callbacks are called afterwards! | |
expect(times_called.green).toEqual(1); | |
expect(green_one).toEqual("green: sanding"); | |
expect(green_two).toEqual("green: priming"); | |
expect(green_three).toEqual("green: painting"); | |
// the callback cache should be reset, so we should be able to execute it again | |
times_called.red = 0; | |
times_called.green = 0; | |
red_done = false; | |
green_done = false; | |
red_callbackable(function() { red_one = "red: something else entirely"; red_done = true; }); | |
green_callbackable(function() { green_one = "green: something else entirely"; green_done = true; }); | |
}); | |
this.waitsFor(function() { | |
return red_done && green_done; | |
}, 20000); | |
runs(function() { | |
expect(times_called.red).toEqual(1); | |
expect(red_one).toEqual("red: something else entirely"); | |
expect(times_called.green).toEqual(1); | |
expect(green_one).toEqual("green: something else entirely"); | |
}); | |
}); | |
}); |
is there a library that already has utilities like this?
http://augmentjs.com has bind
http://supplementjs.com, http://kitcambridge.github.com/maddy, http://functools.kodfabrik.com/man.html have curry/partial application
https://github.com/kriskowal/q - support for sophisticated asynchronous processing; probably can do the above with "promises"
Moved to jsFiddle with new approach by @mkuklis http://jsfiddle.net/JNFQy/1/
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Oh, yeah, the spec is not canonically clean unlinted javascript and I don't really care