|  |  |  |  | # ASAP
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [](https://travis-ci.org/kriskowal/asap) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Promise and asynchronous observer libraries, as well as hand-rolled callback | 
					
						
							|  |  |  |  | programs and libraries, often need a mechanism to postpone the execution of a | 
					
						
							|  |  |  |  | callback until the next available event. | 
					
						
							|  |  |  |  | (See [Designing API’s for Asynchrony][Zalgo].) | 
					
						
							|  |  |  |  | The `asap` function executes a task **as soon as possible** but not before it | 
					
						
							|  |  |  |  | returns, waiting only for the completion of the current event and previously | 
					
						
							|  |  |  |  | scheduled tasks. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```javascript | 
					
						
							|  |  |  |  | asap(function () { | 
					
						
							|  |  |  |  |     // ... | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [Zalgo]: http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | This CommonJS package provides an `asap` module that exports a function that | 
					
						
							|  |  |  |  | executes a task function *as soon as possible*. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ASAP strives to schedule events to occur before yielding for IO, reflow, | 
					
						
							|  |  |  |  | or redrawing. | 
					
						
							|  |  |  |  | Each event receives an independent stack, with only platform code in parent | 
					
						
							|  |  |  |  | frames and the events run in the order they are scheduled. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ASAP provides a fast event queue that will execute tasks until it is | 
					
						
							|  |  |  |  | empty before yielding to the JavaScript engine's underlying event-loop. | 
					
						
							|  |  |  |  | When a task gets added to a previously empty event queue, ASAP schedules a flush | 
					
						
							|  |  |  |  | event, preferring for that event to occur before the JavaScript engine has an | 
					
						
							|  |  |  |  | opportunity to perform IO tasks or rendering, thus making the first task and | 
					
						
							|  |  |  |  | subsequent tasks semantically indistinguishable. | 
					
						
							|  |  |  |  | ASAP uses a variety of techniques to preserve this invariant on different | 
					
						
							|  |  |  |  | versions of browsers and Node.js. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | By design, ASAP prevents input events from being handled until the task | 
					
						
							|  |  |  |  | queue is empty. | 
					
						
							|  |  |  |  | If the process is busy enough, this may cause incoming connection requests to be | 
					
						
							|  |  |  |  | dropped, and may cause existing connections to inform the sender to reduce the | 
					
						
							|  |  |  |  | transmission rate or stall. | 
					
						
							|  |  |  |  | ASAP allows this on the theory that, if there is enough work to do, there is no | 
					
						
							|  |  |  |  | sense in looking for trouble. | 
					
						
							|  |  |  |  | As a consequence, ASAP can interfere with smooth animation. | 
					
						
							|  |  |  |  | If your task should be tied to the rendering loop, consider using | 
					
						
							|  |  |  |  | `requestAnimationFrame` instead. | 
					
						
							|  |  |  |  | A long sequence of tasks can also effect the long running script dialog. | 
					
						
							|  |  |  |  | If this is a problem, you may be able to use ASAP’s cousin `setImmediate` to | 
					
						
							|  |  |  |  | break long processes into shorter intervals and periodically allow the browser | 
					
						
							|  |  |  |  | to breathe. | 
					
						
							|  |  |  |  | `setImmediate` will yield for IO, reflow, and repaint events. | 
					
						
							|  |  |  |  | It also returns a handler and can be canceled. | 
					
						
							|  |  |  |  | For a `setImmediate` shim, consider [YuzuJS setImmediate][setImmediate]. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [setImmediate]: https://github.com/YuzuJS/setImmediate | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Take care. | 
					
						
							|  |  |  |  | ASAP can sustain infinite recursive calls without warning. | 
					
						
							|  |  |  |  | It will not halt from a stack overflow, and it will not consume unbounded | 
					
						
							|  |  |  |  | memory. | 
					
						
							|  |  |  |  | This is behaviorally equivalent to an infinite loop. | 
					
						
							|  |  |  |  | Just as with infinite loops, you can monitor a Node.js process for this behavior | 
					
						
							|  |  |  |  | with a heart-beat signal. | 
					
						
							|  |  |  |  | As with infinite loops, a very small amount of caution goes a long way to | 
					
						
							|  |  |  |  | avoiding problems. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```javascript | 
					
						
							|  |  |  |  | function loop() { | 
					
						
							|  |  |  |  |     asap(loop); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | loop(); | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | In browsers, if a task throws an exception, it will not interrupt the flushing | 
					
						
							|  |  |  |  | of high-priority tasks. | 
					
						
							|  |  |  |  | The exception will be postponed to a later, low-priority event to avoid | 
					
						
							|  |  |  |  | slow-downs. | 
					
						
							|  |  |  |  | In Node.js, if a task throws an exception, ASAP will resume flushing only if—and | 
					
						
							|  |  |  |  | only after—the error is handled by `domain.on("error")` or | 
					
						
							|  |  |  |  | `process.on("uncaughtException")`. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## Raw ASAP
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Checking for exceptions comes at a cost. | 
					
						
							|  |  |  |  | The package also provides an `asap/raw` module that exports the underlying | 
					
						
							|  |  |  |  | implementation which is faster but stalls if a task throws an exception. | 
					
						
							|  |  |  |  | This internal version of the ASAP function does not check for errors. | 
					
						
							|  |  |  |  | If a task does throw an error, it will stall the event queue unless you manually | 
					
						
							|  |  |  |  | call `rawAsap.requestFlush()` before throwing the error, or any time after. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | In Node.js, `asap/raw` also runs all tasks outside any domain. | 
					
						
							|  |  |  |  | If you need a task to be bound to your domain, you will have to do it manually. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ```js | 
					
						
							|  |  |  |  | if (process.domain) { | 
					
						
							|  |  |  |  |     task = process.domain.bind(task); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | rawAsap(task); | 
					
						
							|  |  |  |  | ``` | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## Tasks
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | A task may be any object that implements `call()`. | 
					
						
							|  |  |  |  | A function will suffice, but closures tend not to be reusable and can cause | 
					
						
							|  |  |  |  | garbage collector churn. | 
					
						
							|  |  |  |  | Both `asap` and `rawAsap` accept task objects to give you the option of | 
					
						
							|  |  |  |  | recycling task objects or using higher callable object abstractions. | 
					
						
							|  |  |  |  | See the `asap` source for an illustration. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## Compatibility
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ASAP is tested on Node.js v0.10 and in a broad spectrum of web browsers. | 
					
						
							|  |  |  |  | The following charts capture the browser test results for the most recent | 
					
						
							|  |  |  |  | release. | 
					
						
							|  |  |  |  | The first chart shows test results for ASAP running in the main window context. | 
					
						
							|  |  |  |  | The second chart shows test results for ASAP running in a web worker context. | 
					
						
							|  |  |  |  | Test results are inconclusive (grey) on browsers that do not support web | 
					
						
							|  |  |  |  | workers. | 
					
						
							|  |  |  |  | These data are captured automatically by [Continuous | 
					
						
							|  |  |  |  | Integration][]. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [Continuous Integration]: https://github.com/kriskowal/asap/blob/master/CONTRIBUTING.md | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |  | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## Caveats
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | When a task is added to an empty event queue, it is not always possible to | 
					
						
							|  |  |  |  | guarantee that the task queue will begin flushing immediately after the current | 
					
						
							|  |  |  |  | event. | 
					
						
							|  |  |  |  | However, once the task queue begins flushing, it will not yield until the queue | 
					
						
							|  |  |  |  | is empty, even if the queue grows while executing tasks. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | The following browsers allow the use of [DOM mutation observers][] to access | 
					
						
							|  |  |  |  | the HTML [microtask queue][], and thus begin flushing ASAP's task queue | 
					
						
							|  |  |  |  | immediately at the end of the current event loop turn, before any rendering or | 
					
						
							|  |  |  |  | IO: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [microtask queue]: http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#microtask-queue | 
					
						
							|  |  |  |  | [DOM mutation observers]: http://dom.spec.whatwg.org/#mutation-observers | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | - Android 4–4.3 | 
					
						
							|  |  |  |  | - Chrome 26–34 | 
					
						
							|  |  |  |  | - Firefox 14–29 | 
					
						
							|  |  |  |  | - Internet Explorer 11 | 
					
						
							|  |  |  |  | - iPad Safari 6–7.1 | 
					
						
							|  |  |  |  | - iPhone Safari 7–7.1 | 
					
						
							|  |  |  |  | - Safari 6–7 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | In the absense of mutation observers, there are a few browsers, and situations | 
					
						
							|  |  |  |  | like web workers in some of the above browsers,  where [message channels][] | 
					
						
							|  |  |  |  | would be a useful way to avoid falling back to timers. | 
					
						
							|  |  |  |  | Message channels give direct access to the HTML [task queue][], so the ASAP | 
					
						
							|  |  |  |  | task queue would flush after any already queued rendering and IO tasks, but | 
					
						
							|  |  |  |  | without having the minimum delay imposed by timers. | 
					
						
							|  |  |  |  | However, among these browsers, Internet Explorer 10 and Safari do not reliably | 
					
						
							|  |  |  |  | dispatch messages, so they are not worth the trouble to implement. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [message channels]: http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#message-channels | 
					
						
							|  |  |  |  | [task queue]: http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#concept-task | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | - Internet Explorer 10 | 
					
						
							|  |  |  |  | - Safair 5.0-1 | 
					
						
							|  |  |  |  | - Opera 11-12 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | In the absense of mutation observers, these browsers and the following browsers | 
					
						
							|  |  |  |  | all fall back to using `setTimeout` and `setInterval` to ensure that a `flush` | 
					
						
							|  |  |  |  | occurs. | 
					
						
							|  |  |  |  | The implementation uses both and cancels whatever handler loses the race, since | 
					
						
							|  |  |  |  | `setTimeout` tends to occasionally skip tasks in unisolated circumstances. | 
					
						
							|  |  |  |  | Timers generally delay the flushing of ASAP's task queue for four milliseconds. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | - Firefox 3–13 | 
					
						
							|  |  |  |  | - Internet Explorer 6–10 | 
					
						
							|  |  |  |  | - iPad Safari 4.3 | 
					
						
							|  |  |  |  | - Lynx 2.8.7 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## Heritage
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ASAP has been factored out of the [Q][] asynchronous promise library. | 
					
						
							|  |  |  |  | It originally had a naïve implementation in terms of `setTimeout`, but | 
					
						
							|  |  |  |  | [Malte Ubl][NonBlocking] provided an insight that `postMessage` might be | 
					
						
							|  |  |  |  | useful for creating a high-priority, no-delay event dispatch hack. | 
					
						
							|  |  |  |  | Since then, Internet Explorer proposed and implemented `setImmediate`. | 
					
						
							|  |  |  |  | Robert Katić began contributing to Q by measuring the performance of | 
					
						
							|  |  |  |  | the internal implementation of `asap`, paying particular attention to | 
					
						
							|  |  |  |  | error recovery. | 
					
						
							|  |  |  |  | Domenic, Robert, and Kris Kowal collectively settled on the current strategy of | 
					
						
							|  |  |  |  | unrolling the high-priority event queue internally regardless of what strategy | 
					
						
							|  |  |  |  | we used to dispatch the potentially lower-priority flush event. | 
					
						
							|  |  |  |  | Domenic went on to make ASAP cooperate with Node.js domains. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [Q]: https://github.com/kriskowal/q | 
					
						
							|  |  |  |  | [NonBlocking]: http://www.nonblocking.io/2011/06/windownexttick.html | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | For further reading, Nicholas Zakas provided a thorough article on [The | 
					
						
							|  |  |  |  | Case for setImmediate][NCZ]. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [NCZ]: http://www.nczonline.net/blog/2013/07/09/the-case-for-setimmediate/ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Ember’s RSVP promise implementation later [adopted][RSVP ASAP] the name ASAP but | 
					
						
							|  |  |  |  | further developed the implentation. | 
					
						
							|  |  |  |  | Particularly, The `MessagePort` implementation was abandoned due to interaction | 
					
						
							|  |  |  |  | [problems with Mobile Internet Explorer][IE Problems] in favor of an | 
					
						
							|  |  |  |  | implementation backed on the newer and more reliable DOM `MutationObserver` | 
					
						
							|  |  |  |  | interface. | 
					
						
							|  |  |  |  | These changes were back-ported into this library. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [IE Problems]: https://github.com/cujojs/when/issues/197 | 
					
						
							|  |  |  |  | [RSVP ASAP]: https://github.com/tildeio/rsvp.js/blob/cddf7232546a9cf858524b75cde6f9edf72620a7/lib/rsvp/asap.js | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | In addition, ASAP factored into `asap` and `asap/raw`, such that `asap` remained | 
					
						
							|  |  |  |  | exception-safe, but `asap/raw` provided a tight kernel that could be used for | 
					
						
							|  |  |  |  | tasks that guaranteed that they would not throw exceptions. | 
					
						
							|  |  |  |  | This core is useful for promise implementations that capture thrown errors in | 
					
						
							|  |  |  |  | rejected promises and do not need a second safety net. | 
					
						
							|  |  |  |  | At the same time, the exception handling in `asap` was factored into separate | 
					
						
							|  |  |  |  | implementations for Node.js and browsers, using the the [Browserify][Browser | 
					
						
							|  |  |  |  | Config] `browser` property in `package.json` to instruct browser module loaders | 
					
						
							|  |  |  |  | and bundlers, including [Browserify][], [Mr][], and [Mop][],  to use the | 
					
						
							|  |  |  |  | browser-only implementation. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | [Browser Config]: https://gist.github.com/defunctzombie/4339901 | 
					
						
							|  |  |  |  | [Browserify]: https://github.com/substack/node-browserify | 
					
						
							|  |  |  |  | [Mr]: https://github.com/montagejs/mr | 
					
						
							|  |  |  |  | [Mop]: https://github.com/montagejs/mop | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | ## License
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Copyright 2009-2014 by Contributors | 
					
						
							|  |  |  |  | MIT License (enclosed) | 
					
						
							|  |  |  |  | 
 |