I have promise library called lie, it’s honestly not me trying to reinvent the wheel, I’m aiming to fill the niche of wanting to return promises from your own library where you don’t need all the other tools that when.js and Q have (I did, in a moment of weakness, put in an .all implementation).
As it turns out the crux of making fast promises is coming up with a fast way to get something to resolve asynchronously. The basic idea being, you’re in a function and you want some other function to run but AFTER this function is done running. People will say they want it to get “pushed into the next event loop” but that’s just fancy for “I’d like you to run it after you’re done with this stuff”.
The first instinct is to use setTimeout with a wait time of 0, but due to various reasons setTimeout in many cases has a minimum wait time of 4 not 0, so especially in cases of deeply nested promises this can add up.
Microsoft realized this problem and added a function called setImmediate to IE10 (one of the first cases since the first browser wars of IE being ahead of the curve). A shim was then created by the web team at Barnes and Noble for non IE browsers (um is this where I mention that I used to be an employee of Barnes and Noble when I worked at the MIT COOP, not the one you’re thinking of, the one in building 20). This shim uses quite a bit of black magic to get a very fast deferred execution.
Fast forward to me when I was rewriting setImmediate and lie to use component as part of a blog series on client side package managers I am totally going to finish at some point. Digging through when.js to figure out why it was so much faster than lie with setImmediate and eventually come narrow it down to this function which makes sure that (as dictated by the spec) only function is run at a time, this is the equivalent code in when. The reason it’s so different is because they use different models for pushing the function into the next event loop.
setImmediate uses a model where it works with each function it’s called on individually. when, on the other hand, batches all the functions it’s called on in this loop and calls them all in order next loop.
As far as I can tell these are equivalent behaviors and the speed up may be due to being able to avoid the setTimeout that setImmediate is forced to use. The speed up comes from when.js being able to cut down on what it calls asynchronously, e.g.
Prints this (due to us using post message for asyncness)
But the equivalent with when based immediate only prints it once at the end, because all the calls get put into the same queue until the entire queue is drained, that means that sub calls to immediate DON’T get shunted into the next event loop but added to the end of the current queue.
This is good enough for promises though could in theory cause issues, though I can’t think of any ways to tell the difference without tapping into the listening to global messages (there almost definitely are).
So I did the logical thing and did a combined the cross browser event loop techniques of setImmediate (including using postMessage as a primary method which seems to be faster them messageChanel which when uses, though I have no proof at the moment) with the task model of when to make immediate and it’s a lot faster, which means I’m able to speed up lie drastically too, still haven’t caught when yet though.