Permalink
Browse files

doc: nextTick semantics and justification

  • Loading branch information...
1 parent 19ecc17 commit a52a44e07299f2b46bd88f73c543828af52e60d0 @isaacs isaacs committed Jul 14, 2012
Showing with 89 additions and 16 deletions.
  1. +89 −16 doc/api/process.markdown
View
105 doc/api/process.markdown
@@ -15,10 +15,10 @@ timers may not be scheduled.
Example of listening for `exit`:
- process.on('exit', function () {
- process.nextTick(function () {
- console.log('This will not run');
- });
+ process.on('exit', function() {
+ setTimeout(function() {
+ console.log('This will not run');
+ }, 0);
console.log('About to exit.');
});
@@ -30,11 +30,11 @@ a stack trace and exit) will not occur.
Example of listening for `uncaughtException`:
- process.on('uncaughtException', function (err) {
+ process.on('uncaughtException', function(err) {
console.log('Caught exception: ' + err);
});
- setTimeout(function () {
+ setTimeout(function() {
console.log('This will still run.');
}, 500);
@@ -61,7 +61,7 @@ Example of listening for `SIGINT`:
// Start reading from stdin so we don't exit.
process.stdin.resume();
- process.on('SIGINT', function () {
+ process.on('SIGINT', function() {
console.log('Got SIGINT. Press Control-D to exit.');
});
@@ -75,7 +75,7 @@ A `Writable Stream` to `stdout`.
Example: the definition of `console.log`
- console.log = function (d) {
+ console.log = function(d) {
process.stdout.write(d + '\n');
};
@@ -105,11 +105,11 @@ Example of opening standard input and listening for both events:
process.stdin.resume();
process.stdin.setEncoding('utf8');
- process.stdin.on('data', function (chunk) {
+ process.stdin.on('data', function(chunk) {
process.stdout.write('data: ' + chunk);
});
- process.stdin.on('end', function () {
+ process.stdin.on('end', function() {
process.stdout.write('end');
});
@@ -121,7 +121,7 @@ An array containing the command line arguments. The first element will be
next elements will be any additional command line arguments.
// print process.argv
- process.argv.forEach(function (val, index, array) {
+ process.argv.forEach(function(val, index, array) {
console.log(index + ': ' + val);
});
@@ -313,11 +313,11 @@ may do something other than kill the target process.
Example of sending a signal to yourself:
- process.on('SIGHUP', function () {
+ process.on('SIGHUP', function() {
console.log('Got SIGHUP signal.');
});
- setTimeout(function () {
+ setTimeout(function() {
console.log('Exiting.');
process.exit(0);
}, 100);
@@ -373,12 +373,85 @@ This will generate:
On the next loop around the event loop call this callback.
This is *not* a simple alias to `setTimeout(fn, 0)`, it's much more
-efficient.
+efficient. It typically runs before any other I/O events fire, but there
+are some exceptions. See `process.maxTickDepth` below.
- process.nextTick(function () {
+ process.nextTick(function() {
console.log('nextTick callback');
});
+This is important in developing APIs where you want to give the user the
+chance to assign event handlers after an object has been constructed,
+but before any I/O has occurred.
+
+ function MyThing(options) {
+ this.setupOptions(options);
+
+ process.nextTick(function() {
+ this.startDoingStuff();
+ }.bind(this));
+ }
+
+ var thing = new MyThing();
+ thing.getReadyForStuff();
+
+ // thing.startDoingStuff() gets called now, not before.
+
+It is very important for APIs to be either 100% synchronous or 100%
+asynchronous. Consider this example:
+
+ // WARNING! DO NOT USE! BAD UNSAFE HAZARD!
+ function maybeSync(arg, cb) {
+ if (arg) {
+ cb();
+ return;
+ }
+
+ fs.stat('file', cb);
+ }
+
+This API is hazardous. If you do this:
+
+ maybeSync(true, function() {
+ foo();
+ });
+ bar();
+
+then it's not clear whether `foo()` or `bar()` will be called first.
+
+This approach is much better:
+
+ function definitelyAsync(arg, cb) {
+ if (arg) {
+ process.nextTick(cb);
+ return;
+ }
+
+ fs.stat('file', cb);
+ }
+
+## process.maxTickDepth
+
+* {Number} Default = 1000
+
+Callbacks passed to `process.nextTick` will *usually* be called at the
+end of the current flow of execution, and are thus approximately as fast
+as calling a function synchronously. Left unchecked, this would starve
+the event loop, preventing any I/O from occurring.
+
+Consider this code:
+
+ process.nextTick(function foo() {
+ process.nextTick(foo);
+ });
+
+In order to avoid the situation where Node is blocked by an infinite
+loop of recursive series of nextTick calls, it defers to allow some I/O
+to be done every so often.
+
+The `process.maxTickDepth` value is the maximum depth of
+nextTick-calling nextTick-callbacks that will be evaluated before
+allowing other forms of I/O to occur.
## process.umask([mask])
@@ -411,7 +484,7 @@ a diff reading, useful for benchmarks and measuring intervals:
var t = process.hrtime();
// [ 1800216, 927643717 ]
- setTimeout(function () {
+ setTimeout(function() {
t = process.hrtime(t);
// [ 1, 6962306 ]

0 comments on commit a52a44e

Please sign in to comment.