Skip to content

Instantly share code, notes, and snippets.

@rkatic
Last active January 19, 2021 07:31
Show Gist options
  • Save rkatic/4695131 to your computer and use it in GitHub Desktop.
Save rkatic/4695131 to your computer and use it in GitHub Desktop.
Cross-browser and optimized way to postpone a function execution to next "tick".
// Based on the Q.nextTick implementation https://github.com/kriskowal/q/pull/195.
var later = (function(){
var head = { task: void 0, next: null }, tail = head,
maxPendingTicks = 2, pendingTicks = 0, queuedTasks = 0, usedTicks = 0,
requestTick;
var onTick = function() {
--pendingTicks;
if ( ++usedTicks >= maxPendingTicks ) {
// Amortize delay after thrown exceptions.
maxPendingTicks *= 2;
var expectedTicks = queuedTasks && Math.min( queuedTasks - 1, maxPendingTicks );
while ( pendingTicks < expectedTicks ) {
++pendingTicks;
requestTick();
}
usedTicks = 0;
}
while ( queuedTasks ) {
--queuedTasks; // decrement here to ensure it's never negative
head = head.next;
var task = head.task;
head.task = void 0;
task();
}
usedTicks = 0;
};
var later = function( task ) {
tail = tail.next = { task: task, next: null };
if ( ++queuedTasks > pendingTicks && pendingTicks < maxPendingTicks ) {
++pendingTicks;
requestTick();
}
};
var win = typeof window !== "undefined" && window;
if ( typeof process !== "undefined" && "nextTick" in process ) {
requestTick = function() {
process.nextTick( onTick );
};
} else if ( typeof win.setImmediate === "function" ) {
requestTick = function() {
win.setImmediate( onTick );
};
} else if ( typeof MessageChannel !== "undefined" ) {
var channel = new MessageChannel();
channel.port1.onmessage = onTick;
requestTick = function() {
channel.port2.postMessage(0);
};
} else {
requestTick = function() {
setTimeout( onTick, 0 );
};
if ( win && typeof Image !== "undefined" ) {
var c = 0;
var requestTickViaImage = function( cb ) {
var img = new Image();
img.onerror = cb || onTick;
img.src = 'data:image/png,';
};
try {
requestTickViaImage(function() {
if ( --c === 0 ) {
requestTick = requestTickViaImage;
}
});
++c;
} catch (e) {}
c && setTimeout(function() {
c = 0;
}, 0);
}
}
return later;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment