• Stars
    star
    604
  • Rank 71,295 (Top 2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 11 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

High-priority task queue for Node.js and browsers

ASAP

Build Status

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.) 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.

asap(function () {
    // ...
});

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.

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.

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.

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.

Browser Compatibility

Compatibility in Web Workers

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:

  • 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 absence 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.

  • Internet Explorer 10
  • Safari 5.0-1
  • Opera 11-12

In the absence 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 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.

For further reading, Nicholas Zakas provided a thorough article on The Case for setImmediate.

Ember’s RSVP promise implementation later adopted the name ASAP but further developed the implentation. Particularly, The MessagePort implementation was abandoned due to interaction problems with Mobile Internet Explorer in favor of an implementation backed on the newer and more reliable DOM MutationObserver interface. These changes were back-ported into this library.

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 property in package.json to instruct browser module loaders and bundlers, including Browserify, Mr, and Mop, to use the browser-only implementation.

License

Copyright 2009-2014 by Contributors MIT License (enclosed)

More Repositories

1

q

A promise library for JavaScript
JavaScript
14,957
star
2

gtor

A General Theory of Reactivity
JavaScript
3,004
star
3

q-io

Interfaces for IO using Q promises in JavaScript on Node
JavaScript
315
star
4

q-connection

A JavaScript library for communicating asynchronously with remote objects using promises.
JavaScript
240
star
5

uncommonjs

Uncommonly designed JavaScript specifications
JavaScript
172
star
6

zip

An implementation of unzip in JavaScript for Node
JavaScript
85
star
7

tengwarjs

A Tengwar (J.R.R. Tolkien’s Elvish alphabet) transcriber for ES5 and HTML5
JavaScript
55
star
8

util

Out of service, use Collections — The missing methods of JavaScript
JavaScript
44
star
9

context

JavaScript context cancellation, deadlines, storage
JavaScript
43
star
10

collections

JavaScript collections with idiomatic interfaces
JavaScript
33
star
11

3rin.gs

An online map of Middle Earth
HTML
30
star
12

chiron

Missing types and methods for JavaScript
JavaScript
28
star
13

narwhal-lib

Narwhal's pure-JavaScript standard library as a package usable on other CommonJS engines.
JavaScript
24
star
14

qq

Out of service — Extensions for the Q promise library for JavaScript
JavaScript
24
star
15

terminal

A JavaScript HTML5/VT100 Terminal Emulator
JavaScript
22
star
16

q-fs

Out of service — Use Q-IO instead.
JavaScript
21
star
17

qooqbooq

A primer on the care and feeding of asynchronous promises
JavaScript
20
star
18

tigerblood

Just kidding — Eventually Winning in JavaScript (CommonJS/Promises/A,B,D)
JavaScript
19
star
19

q-http

Out of service — Please use Q-IO
JavaScript
15
star
20

xbin

~/bin
Shell
15
star
21

wiky

A Wiki markup to and from HTML converter written in JavaScript (LGPL)
JavaScript
13
star
22

iterator

Out of service: consider "collections" — JavaScript iterator tools
JavaScript
12
star
23

mimeparse

Basic functions for handling mime-types as a JavaScript package
JavaScript
12
star
24

tusk

A JavaScript package manager
JavaScript
12
star
25

cops

A terminal UI library for Go
Go
11
star
26

whatsupdoc

Out of service — A pure JavaScript inline JavaScript documentation parser and formatter CommonJS package.
JavaScript
11
star
27

codish

A Jack/Narwhal/GAE back-end for the Codish Lexicon website.
JavaScript
10
star
28

jaque

Out of service — Use q-io/http-apps
JavaScript
10
star
29

q-require

Out of service — Please use Mr instead
JavaScript
9
star
30

fs-boot

Out of service — Please use Q-IO instead
JavaScript
8
star
31

lode

Out of service: consider "mr" — A package-aware asynchronous JavaScript module system
JavaScript
8
star
32

tale.js

Tale, a game
JavaScript
8
star
33

tale

An immersive adventure game set on the faces of a six-sided die (real-time, web, text and command mmorpg)
Python
7
star
34

thatsallfolks

A pure JavaScript template parsing and formatting package based on Narwhal's resource overlays.
JavaScript
7
star
35

gtor-demos

Animated visualizations for A General Theory of Reactivity
JavaScript
7
star
36

argunauts

JavaScript
5
star
37

url2

Augments Node.js’s URL library
JavaScript
5
star
38

pop-observe

Property, range, map, and set change observers for arrays, objects, and other instances.
JavaScript
5
star
39

mkroot

Yes, roots are my trade. I am a rooter. My name is mkroot. I arrange, design, and sell roots.
Shell
5
star
40

swl

An HTML preprocessor I wrote back in Y2K. Compare to Markdown.
Perl
4
star
41

transcode

Out of service — Character set transcoder for NodeJS, built on libiconv
C++
4
star
42

blog

Ask a Wizard blog
4
star
43

peruacru

Escape from Peruácru Island
JavaScript
3
star
44

pop-swap

Range content change operator for arrays and array like JavaScript objects
JavaScript
3
star
45

rezult

JavaScript value or error object
JavaScript
3
star
46

narwhal-node

Out of service — An old and busted implementation of a Node embedding for Narwhal.
JavaScript
3
star
47

pop-zip

Zip and unzip (also called matrix transpose) for arrays and other collections.
JavaScript
3
star
48

gol

Game of Life Demo
JavaScript
3
star
49

pop-equals

Deep equality polymorphic operator for arbitrary JavaScript objects
JavaScript
2
star
50

pop-iterate

Polymorphic iterator operator for JavaScript objects
JavaScript
2
star
51

home

My home directory
Vim Script
2
star
52

bandnames

Band name ideas (mostly bad)
2
star
53

gol.aelf.land

Game of Life Browser
JavaScript
2
star
54

jscrypto

Fast symmetric cryptography in Javascript
JavaScript
2
star
55

planes

Python on Planes: middleware and reusable applications for persistent state web services
Python
2
star
56

pop-has

Polymorphic has operator for checking whether an equivalent value exists in a JavaScript collection
JavaScript
2
star
57

watablag

Temporary.
CSS
2
star
58

silk

A smooth, free icon set, containing over 700 16-by-16 pixel icons in strokably-soft PNG format, packaged for Narwhal.
2
star
59

pop-compare

Polymorphic deep comparison operator for arbitrary JavaScript values
JavaScript
2
star
60

pop-clone

A polymorphic operator for cloning JavaScript object graphs
JavaScript
2
star
61

codi.sh

JavaScript
2
star
62

montage-simple-flow

JavaScript
2
star
63

pop-hash

A hash operator for arbitrary JavaScript objects, for browsers and Node.js
JavaScript
2
star
64

montage-repetition-demo

A demo of a bare MontageJS Repetition, with add and remove buttons in the Digit touch widget set.
JavaScript
1
star
65

montage-tree-controller-demo

A demo of the new MontageJS TreeController
JavaScript
1
star
66

pop-arrayify

Transforms arbitrary collections into arrays by whatever means they support
JavaScript
1
star
67

emone.then.land

Emonë script transcriber
JavaScript
1
star
68

kriskowal.github.io

All the things.
1
star
69

test

JavaScript
1
star
70

zp

Zero-prefixed function calls in strings
JavaScript
1
star
71

yogabylydia.com

ॐ Yoga By Lydia ॐ
HTML
1
star
72

felis-cursus

JavaScript
1
star
73

sh.codi.sh

modal web shell
JavaScript
1
star
74

mr-coffee

CoffeeScript translator for Montage Require 2
JavaScript
1
star
75

engage

JavaScript
1
star
76

delve.aelf.land

Front-end for the aelf.land world editor
JavaScript
1
star
77

pop-clear

Clears objects, arrays, and objects that override the clear method.
JavaScript
1
star
78

q-comm

Out of service — Q-Comm has been renamed Q-Connection
1
star
79

mini-map

A very small subset of ES6 Map that is good enough for small sizes
JavaScript
1
star