Last active
December 28, 2015 11:29
-
-
Save pdokas/7493326 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
var asap = (function(global) { | |
"use strict"; | |
// Use the fastest possible means to execute a task in a future turn | |
// of the event loop. | |
// linked list of tasks (single, with head node) | |
var head = {task: void 0, next: null}; | |
var tail = head; | |
var flushing = false; | |
var requestFlush = void 0; | |
var hasSetImmediate = typeof setImmediate === "function"; | |
var domain; | |
// Avoid shims from browserify. | |
// The existence of `global` in browsers is guaranteed by browserify. | |
var process = global.process; | |
// Note that some fake-Node environments, | |
// like the Mocha test runner, introduce a `process` global. | |
var isNodeJS = !!process && ({}).toString.call(process) === "[object process]"; | |
function flush() { | |
/* jshint loopfunc: true */ | |
while (head.next) { | |
head = head.next; | |
var task = head.task; | |
head.task = void 0; | |
try { | |
task(); | |
} catch (e) { | |
if (isNodeJS) { | |
// In node, uncaught exceptions are considered fatal errors. | |
// Re-throw them to interrupt flushing! | |
// Ensure continuation if an uncaught exception is suppressed | |
// listening process.on("uncaughtException") or domain("error"). | |
requestFlush(); | |
throw e; | |
} else { | |
// In browsers, uncaught exceptions are not fatal. | |
// Re-throw them asynchronously to avoid slow-downs. | |
setTimeout(function () { | |
throw e; | |
}, 0); | |
} | |
} | |
} | |
flushing = false; | |
} | |
if (isNodeJS) { | |
// Node.js | |
requestFlush = function () { | |
// Ensure flushing is not bound to any domain. | |
var currentDomain = process.domain; | |
if (currentDomain) { | |
domain = domain || (1,require)("domain"); | |
domain.active = process.domain = null; | |
} | |
// Avoid tick recursion - use setImmediate if it exists. | |
if (flushing && hasSetImmediate) { | |
setImmediate(flush); | |
} else { | |
process.nextTick(flush); | |
} | |
if (currentDomain) { | |
domain.active = process.domain = currentDomain; | |
} | |
}; | |
} else if (hasSetImmediate) { | |
// In IE10, or https://github.com/NobleJS/setImmediate | |
requestFlush = function () { | |
setImmediate(flush); | |
}; | |
} else if (typeof MessageChannel !== "undefined") { | |
// modern browsers | |
// http://www.nonblocking.io/2011/06/windownexttick.html | |
var channel = new MessageChannel(); | |
// At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create | |
// working message ports the first time a page loads. | |
channel.port1.onmessage = function () { | |
requestFlush = requestPortFlush; | |
channel.port1.onmessage = flush; | |
flush(); | |
}; | |
var requestPortFlush = function () { | |
// Opera requires us to provide a message payload, regardless of | |
// whether we use it. | |
channel.port2.postMessage(0); | |
}; | |
requestFlush = function () { | |
setTimeout(flush, 0); | |
requestPortFlush(); | |
}; | |
} else { | |
// old browsers | |
requestFlush = function () { | |
setTimeout(flush, 0); | |
}; | |
} | |
function asap(task) { | |
if (isNodeJS && process.domain) { | |
task = process.domain.bind(task); | |
} | |
tail = tail.next = {task: task, next: null}; | |
if (!flushing) { | |
requestFlush(); | |
flushing = true; | |
} | |
}; | |
return asap; | |
})(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment