1"use strict"; 2 3var rawAsap = require("./raw"); 4var freeTasks = []; 5 6/** 7 * Calls a task as soon as possible after returning, in its own event, with 8 * priority over IO events. An exception thrown in a task can be handled by 9 * `process.on("uncaughtException") or `domain.on("error")`, but will otherwise 10 * crash the process. If the error is handled, all subsequent tasks will 11 * resume. 12 * 13 * @param {{call}} task A callable object, typically a function that takes no 14 * arguments. 15 */ 16module.exports = asap; 17function asap(task) { 18 var rawTask; 19 if (freeTasks.length) { 20 rawTask = freeTasks.pop(); 21 } else { 22 rawTask = new RawTask(); 23 } 24 rawTask.task = task; 25 rawTask.domain = process.domain; 26 rawAsap(rawTask); 27} 28 29function RawTask() { 30 this.task = null; 31 this.domain = null; 32} 33 34RawTask.prototype.call = function () { 35 if (this.domain) { 36 this.domain.enter(); 37 } 38 var threw = true; 39 try { 40 this.task.call(); 41 threw = false; 42 // If the task throws an exception (presumably) Node.js restores the 43 // domain stack for the next event. 44 if (this.domain) { 45 this.domain.exit(); 46 } 47 } finally { 48 // We use try/finally and a threw flag to avoid messing up stack traces 49 // when we catch and release errors. 50 if (threw) { 51 // In Node.js, uncaught exceptions are considered fatal errors. 52 // Re-throw them to interrupt flushing! 53 // Ensure that flushing continues if an uncaught exception is 54 // suppressed listening process.on("uncaughtException") or 55 // domain.on("error"). 56 rawAsap.requestFlush(); 57 } 58 // If the task threw an error, we do not want to exit the domain here. 59 // Exiting the domain would prevent the domain from catching the error. 60 this.task = null; 61 this.domain = null; 62 freeTasks.push(this); 63 } 64}; 65 66