Thursday, June 16, 2011

window.nextTick

Node.js has a special API called process.nextTick which schedules a function to be executed immediately the next time the event loop is idle.
Web applications often try achieve a similar result using setTimeout. The problem is that setTimeout with a zero time parameter does not schedule for immediately but rather for some time a little later. This *can* lead to real performance problems.
I benchmarked a couple ways to do postMessage between workers, iframes and on the current window itself. Turns out doing postMessage on your current window might be a really good alternative to implement process.nextTick in browsers.
Please tell me what I did wrong in my benchmark.

3 comments:

Edvakf said...

This is slightly faster than window.postMessage and doesn't interfere with other onmessage listeners.

var mc = new MessageChannel;
function nextTick(callback){
mc.port1.onmessage = callback;
mc.port2.postMessage(0);
}

HOWEVER, some browsers (at least Opera) does not redraw after each postMessage async operation, so it can't be used for animation.

I think it's best to do what JSDeferred does.

function nextTick(callback){
var img = new Image;
img.onerror = callback;
img.src = 'data:image/png,' + Math.random();
}

(need special care for IE)

Malte said...

Thanks, interesting variants!

Not rendering is actually a nice property.

requestAnimationFrame should be used for that anyway.

Kris Kowal said...

Here's the whole implementation of nextTick based on MessageChannel.

var channel = new MessageChannel();
// linked list of tasks (single, with head node)
var head = {}, tail = head;
channel.port1.onmessage = function () {
var next = head.next;
var task = next.task;
head = next;
task();
};
var nextTick = function (task) {
tail = tail.next = {task: task};
channel.port2.postMessage();
};