Let’s start with the problem: I was writing some set of tests which were highly dependent on triggering actions and waiting events propagation to continue. This usually involves a lot of callbacks from short timeouts or event listeners, and you end up with code like this: [semi-pseudocode]

Which is the modern day equivalent of spreading gotos everywhere on your code (“oh, the horror!”), and makes it very hard to follow the intended logic, specially if you didn’t aptly name your functions with numbers to help you out.

To improve that, we can avoid nesting all of the calls and write a sequential function, and use the yield keyword to exit the function at one point and then continue running it from that point on. It’s like a set of sleep/wakeUp calls, and all the wakeUp control won’t be so mixed with our logic. So we would write as follows:

Cleaner, isn’t it? Oh, and just a note, when you use this make sure you don’t end up subtly changing the logic of your calls, unlike “a friend of mine” who did this and broke the tests he had written. :)

The trick of the zero timeout using postMessage is really cool. One thing I was wondering: if we exit the function with the specific goal of returning to the event loop, is it guaranteed that all the current pending events will be processed before the function being called again? Or does the 10~20ms clamping ended up helping us here?
If it is guaranteed, I think it’d be really useful to have that ZeroTimeout function available in some helper file of the test harness. (EventUtils?)

Oh, and it’s really good to see old CS concepts come back into fashion. I think coroutines are a very clean way to implement asynchronous logic, and that one of the worst effects of C being dominant for so many years was that coroutines fell into disuse.

That was a very cool read, thanks Sid.
Another cool project related to this is node.js (nodejs.org). Have you seen it? It’s a JS library that makes all File I/O through events, even calls which are blocking in the underlying filesystem.