Node.js v0.10.48 Manual & Documentation
Table of Contents
- About this Documentation
- Synopsis
- Global Objects
- console
- Timers
- Modules
- Addons
- process
- Event: 'exit'
- Event: 'uncaughtException'
- Signal Events
- process.stdout
- process.stderr
- process.stdin
- process.argv
- process.execPath
- process.execArgv
- process.abort()
- process.chdir(directory)
- process.cwd()
- process.env
- process.exit([code])
- process.getgid()
- process.setgid(id)
- process.getuid()
- process.setuid(id)
- process.getgroups()
- process.setgroups(groups)
- process.initgroups(user, extra_group)
- process.version
- process.versions
- process.config
- process.kill(pid, [signal])
- process.pid
- process.title
- process.arch
- process.platform
- process.memoryUsage()
- process.nextTick(callback)
- process.maxTickDepth
- process.umask([mask])
- process.uptime()
- process.hrtime()
- util
- util.format(format, [...])
- util.debug(string)
- util.error([...])
- util.puts([...])
- util.print([...])
- util.log(string)
- util.inspect(object, [options])
- util.isArray(object)
- util.isRegExp(object)
- util.isDate(object)
- util.isError(object)
- util.pump(readableStream, writableStream, [callback])
- util.inherits(constructor, superConstructor)
- Events
- Class: events.EventEmitter
- emitter.addListener(event, listener)
- emitter.on(event, listener)
- emitter.once(event, listener)
- emitter.removeListener(event, listener)
- emitter.removeAllListeners([event])
- emitter.setMaxListeners(n)
- emitter.listeners(event)
- emitter.emit(event, [arg1], [arg2], [...])
- Class Method: EventEmitter.listenerCount(emitter, event)
- Event: 'newListener'
- Event: 'removeListener'
- Class: events.EventEmitter
- Domain
- Buffer
- Class: Buffer
- new Buffer(size)
- new Buffer(array)
- new Buffer(str, [encoding])
- Class Method: Buffer.isEncoding(encoding)
- buf.write(string, [offset], [length], [encoding])
- buf.toString([encoding], [start], [end])
- buf.toJSON()
- buf[index]
- Class Method: Buffer.isBuffer(obj)
- Class Method: Buffer.byteLength(string, [encoding])
- Class Method: Buffer.concat(list, [totalLength])
- buf.length
- buf.copy(targetBuffer, [targetStart], [sourceStart], [sourceEnd])
- buf.slice([start], [end])
- buf.readUInt8(offset, [noAssert])
- buf.readUInt16LE(offset, [noAssert])
- buf.readUInt16BE(offset, [noAssert])
- buf.readUInt32LE(offset, [noAssert])
- buf.readUInt32BE(offset, [noAssert])
- buf.readInt8(offset, [noAssert])
- buf.readInt16LE(offset, [noAssert])
- buf.readInt16BE(offset, [noAssert])
- buf.readInt32LE(offset, [noAssert])
- buf.readInt32BE(offset, [noAssert])
- buf.readFloatLE(offset, [noAssert])
- buf.readFloatBE(offset, [noAssert])
- buf.readDoubleLE(offset, [noAssert])
- buf.readDoubleBE(offset, [noAssert])
- buf.writeUInt8(value, offset, [noAssert])
- buf.writeUInt16LE(value, offset, [noAssert])
- buf.writeUInt16BE(value, offset, [noAssert])
- buf.writeUInt32LE(value, offset, [noAssert])
- buf.writeUInt32BE(value, offset, [noAssert])
- buf.writeInt8(value, offset, [noAssert])
- buf.writeInt16LE(value, offset, [noAssert])
- buf.writeInt16BE(value, offset, [noAssert])
- buf.writeInt32LE(value, offset, [noAssert])
- buf.writeInt32BE(value, offset, [noAssert])
- buf.writeFloatLE(value, offset, [noAssert])
- buf.writeFloatBE(value, offset, [noAssert])
- buf.writeDoubleLE(value, offset, [noAssert])
- buf.writeDoubleBE(value, offset, [noAssert])
- buf.fill(value, [offset], [end])
- buffer.INSPECT_MAX_BYTES
- Class: SlowBuffer
- Class: Buffer
- Stream
- Crypto
- crypto.getCiphers()
- crypto.getHashes()
- crypto.createCredentials(details)
- crypto.createHash(algorithm)
- Class: Hash
- crypto.createHmac(algorithm, key)
- Class: Hmac
- crypto.createCipher(algorithm, password)
- crypto.createCipheriv(algorithm, key, iv)
- Class: Cipher
- crypto.createDecipher(algorithm, password)
- crypto.createDecipheriv(algorithm, key, iv)
- Class: Decipher
- crypto.createSign(algorithm)
- Class: Sign
- crypto.createVerify(algorithm)
- Class: Verify
- crypto.createDiffieHellman(prime_length)
- crypto.createDiffieHellman(prime, [encoding])
- Class: DiffieHellman
- diffieHellman.generateKeys([encoding])
- diffieHellman.computeSecret(other_public_key, [input_encoding], [output_encoding])
- diffieHellman.getPrime([encoding])
- diffieHellman.getGenerator([encoding])
- diffieHellman.getPublicKey([encoding])
- diffieHellman.getPrivateKey([encoding])
- diffieHellman.setPublicKey(public_key, [encoding])
- diffieHellman.setPrivateKey(private_key, [encoding])
- crypto.getDiffieHellman(group_name)
- crypto.pbkdf2(password, salt, iterations, keylen, callback)
- crypto.pbkdf2Sync(password, salt, iterations, keylen)
- crypto.randomBytes(size, [callback])
- crypto.pseudoRandomBytes(size, [callback])
- crypto.DEFAULT_ENCODING
- Recent API Changes
- TLS (SSL)
- Protocol support
- Client-initiated renegotiation attack mitigation
- NPN and SNI
- tls.getCiphers()
- tls.createServer(options, [secureConnectionListener])
- tls.SLAB_BUFFER_SIZE
- tls.connect(options, [callback])
- tls.connect(port, [host], [options], [callback])
- tls.createSecurePair([credentials], [isServer], [requestCert], [rejectUnauthorized])
- Class: SecurePair
- Class: tls.Server
- Class: CryptoStream
- Class: tls.CleartextStream
- StringDecoder
- File System
- fs.rename(oldPath, newPath, callback)
- fs.renameSync(oldPath, newPath)
- fs.ftruncate(fd, len, callback)
- fs.ftruncateSync(fd, len)
- fs.truncate(path, len, callback)
- fs.truncateSync(path, len)
- fs.chown(path, uid, gid, callback)
- fs.chownSync(path, uid, gid)
- fs.fchown(fd, uid, gid, callback)
- fs.fchownSync(fd, uid, gid)
- fs.lchown(path, uid, gid, callback)
- fs.lchownSync(path, uid, gid)
- fs.chmod(path, mode, callback)
- fs.chmodSync(path, mode)
- fs.fchmod(fd, mode, callback)
- fs.fchmodSync(fd, mode)
- fs.lchmod(path, mode, callback)
- fs.lchmodSync(path, mode)
- fs.stat(path, callback)
- fs.lstat(path, callback)
- fs.fstat(fd, callback)
- fs.statSync(path)
- fs.lstatSync(path)
- fs.fstatSync(fd)
- fs.link(srcpath, dstpath, callback)
- fs.linkSync(srcpath, dstpath)
- fs.symlink(srcpath, dstpath, [type], callback)
- fs.symlinkSync(srcpath, dstpath, [type])
- fs.readlink(path, callback)
- fs.readlinkSync(path)
- fs.realpath(path, [cache], callback)
- fs.realpathSync(path, [cache])
- fs.unlink(path, callback)
- fs.unlinkSync(path)
- fs.rmdir(path, callback)
- fs.rmdirSync(path)
- fs.mkdir(path, [mode], callback)
- fs.mkdirSync(path, [mode])
- fs.readdir(path, callback)
- fs.readdirSync(path)
- fs.close(fd, callback)
- fs.closeSync(fd)
- fs.open(path, flags, [mode], callback)
- fs.openSync(path, flags, [mode])
- fs.utimes(path, atime, mtime, callback)
- fs.utimesSync(path, atime, mtime)
- fs.futimes(fd, atime, mtime, callback)
- fs.futimesSync(fd, atime, mtime)
- fs.fsync(fd, callback)
- fs.fsyncSync(fd)
- fs.write(fd, buffer, offset, length, position, callback)
- fs.writeSync(fd, buffer, offset, length, position)
- fs.read(fd, buffer, offset, length, position, callback)
- fs.readSync(fd, buffer, offset, length, position)
- fs.readFile(filename, [options], callback)
- fs.readFileSync(filename, [options])
- fs.writeFile(filename, data, [options], callback)
- fs.writeFileSync(filename, data, [options])
- fs.appendFile(filename, data, [options], callback)
- fs.appendFileSync(filename, data, [options])
- fs.watchFile(filename, [options], listener)
- fs.unwatchFile(filename, [listener])
- fs.watch(filename, [options], [listener])
- fs.exists(path, callback)
- fs.existsSync(path)
- Class: fs.Stats
- fs.createReadStream(path, [options])
- Class: fs.ReadStream
- fs.createWriteStream(path, [options])
- Class: fs.WriteStream
- Class: fs.FSWatcher
- Path
- net
- net.createServer([options], [connectionListener])
- net.connect(options, [connectionListener])
- net.createConnection(options, [connectionListener])
- net.connect(port, [host], [connectListener])
- net.createConnection(port, [host], [connectListener])
- net.connect(path, [connectListener])
- net.createConnection(path, [connectListener])
- Class: net.Server
- server.listen(port, [host], [backlog], [callback])
- server.listen(path, [callback])
- server.listen(handle, [callback])
- server.close([callback])
- server.address()
- server.unref()
- server.ref()
- server.maxConnections
- server.connections
- server.getConnections(callback)
- Event: 'listening'
- Event: 'connection'
- Event: 'close'
- Event: 'error'
- Class: net.Socket
- new net.Socket([options])
- socket.connect(port, [host], [connectListener])
- socket.connect(path, [connectListener])
- socket.bufferSize
- socket.setEncoding([encoding])
- socket.write(data, [encoding], [callback])
- socket.end([data], [encoding])
- socket.destroy()
- socket.pause()
- socket.resume()
- socket.setTimeout(timeout, [callback])
- socket.setNoDelay([noDelay])
- socket.setKeepAlive([enable], [initialDelay])
- socket.address()
- socket.unref()
- socket.ref()
- socket.remoteAddress
- socket.remotePort
- socket.localAddress
- socket.localPort
- socket.bytesRead
- socket.bytesWritten
- Event: 'connect'
- Event: 'data'
- Event: 'end'
- Event: 'timeout'
- Event: 'drain'
- Event: 'error'
- Event: 'close'
- net.isIP(input)
- net.isIPv4(input)
- net.isIPv6(input)
- UDP / Datagram Sockets
- dgram.createSocket(type, [callback])
- Class: dgram.Socket
- Event: 'message'
- Event: 'listening'
- Event: 'close'
- Event: 'error'
- socket.send(buf, offset, length, port, address, [callback])
- socket.bind(port, [address], [callback])
- socket.close()
- socket.address()
- socket.setBroadcast(flag)
- socket.setTTL(ttl)
- socket.setMulticastTTL(ttl)
- socket.setMulticastLoopback(flag)
- socket.addMembership(multicastAddress, [multicastInterface])
- socket.dropMembership(multicastAddress, [multicastInterface])
- socket.unref()
- socket.ref()
- DNS
- dns.lookup(domain, [family], callback)
- dns.resolve(domain, [rrtype], callback)
- dns.resolve4(domain, callback)
- dns.resolve6(domain, callback)
- dns.resolveMx(domain, callback)
- dns.resolveTxt(domain, callback)
- dns.resolveSrv(domain, callback)
- dns.resolveNs(domain, callback)
- dns.resolveCname(domain, callback)
- dns.reverse(ip, callback)
- Error codes
- Implementation considerations
- HTTP
- http.STATUS_CODES
- http.createServer([requestListener])
- http.createClient([port], [host])
- Class: http.Server
- Event: 'request'
- Event: 'connection'
- Event: 'close'
- Event: 'checkContinue'
- Event: 'connect'
- Event: 'upgrade'
- Event: 'clientError'
- server.listen(port, [hostname], [backlog], [callback])
- server.listen(path, [callback])
- server.listen(handle, [callback])
- server.close([callback])
- server.maxHeadersCount
- server.setTimeout(msecs, callback)
- server.timeout
- Class: http.ServerResponse
- Event: 'close'
- Event: 'finish'
- response.writeContinue()
- response.writeHead(statusCode, [reasonPhrase], [headers])
- response.setTimeout(msecs, callback)
- response.statusCode
- response.setHeader(name, value)
- response.headersSent
- response.sendDate
- response.getHeader(name)
- response.removeHeader(name)
- response.write(chunk, [encoding])
- response.addTrailers(headers)
- response.end([data], [encoding])
- http.request(options, [callback])
- http.get(options, [callback])
- Class: http.Agent
- http.globalAgent
- Class: http.ClientRequest
- http.IncomingMessage
- HTTPS
- URL
- Query String
- punycode
- Readline
- REPL
- Executing JavaScript
- Child Process
- Assert
- assert.fail(actual, expected, message, operator)
- assert(value, [message]), assert.ok(value, [message])
- assert.equal(actual, expected, [message])
- assert.notEqual(actual, expected, [message])
- assert.deepEqual(actual, expected, [message])
- assert.notDeepEqual(actual, expected, [message])
- assert.strictEqual(actual, expected, [message])
- assert.notStrictEqual(actual, expected, [message])
- assert.throws(block, [error], [message])
- assert.doesNotThrow(block, [message])
- assert.ifError(value)
- TTY
- Zlib
- Examples
- zlib.createGzip([options])
- zlib.createGunzip([options])
- zlib.createDeflate([options])
- zlib.createInflate([options])
- zlib.createDeflateRaw([options])
- zlib.createInflateRaw([options])
- zlib.createUnzip([options])
- Class: zlib.Zlib
- Class: zlib.Gzip
- Class: zlib.Gunzip
- Class: zlib.Deflate
- Class: zlib.Inflate
- Class: zlib.DeflateRaw
- Class: zlib.InflateRaw
- Class: zlib.Unzip
- Convenience Methods
- zlib.deflate(buf, callback)
- zlib.deflateRaw(buf, callback)
- zlib.gzip(buf, callback)
- zlib.gunzip(buf, callback)
- zlib.inflate(buf, callback)
- zlib.inflateRaw(buf, callback)
- zlib.unzip(buf, callback)
- Options
- Memory Usage Tuning
- Constants
- os
- Debugger
- Cluster
About this Documentation#
The goal of this documentation is to comprehensively explain the Node.js API, both from a reference as well as a conceptual point of view. Each section describes a built-in module or high-level concept.
Where appropriate, property types, method arguments, and the arguments provided to event handlers are detailed in a list underneath the topic heading.
Every .html
document has a corresponding .json
document presenting
the same information in a structured manner. This feature is
experimental, and added for the benefit of IDEs and other utilities that
wish to do programmatic things with the documentation.
Every .html
and .json
file is generated based on the corresponding
.markdown
file in the doc/api/
folder in node's source tree. The
documentation is generated using the tools/doc/generate.js
program.
The HTML template is located at doc/template.html
.
Stability Index#
Throughout the documentation, you will see indications of a section's stability. The Node.js API is still somewhat changing, and as it matures, certain parts are more reliable than others. Some are so proven, and so relied upon, that they are unlikely to ever change at all. Others are brand new and experimental, or known to be hazardous and in the process of being redesigned.
The stability indices are as follows:
Stability: 0 - Deprecated This feature is known to be problematic, and changes are planned. Do not rely on it. Use of the feature may cause warnings. Backwards compatibility should not be expected.
Stability: 1 - Experimental This feature was introduced recently, and may change or be removed in future versions. Please try it out and provide feedback. If it addresses a use-case that is important to you, tell the node core team.
Stability: 2 - Unstable The API is in the process of settling, but has not yet had sufficient real-world testing to be considered stable. Backwards-compatibility will be maintained if reasonable.
Stability: 3 - Stable The API has proven satisfactory, but cleanup in the underlying code may cause minor changes. Backwards-compatibility is guaranteed.
Stability: 4 - API Frozen This API has been tested extensively in production and is unlikely to ever have to change.
Stability: 5 - Locked Unless serious bugs are found, this code will not ever change. Please do not suggest changes in this area; they will be refused.
JSON Output#
Stability: 1 - Experimental
Every HTML file in the markdown has a corresponding JSON file with the same data.
This feature is new as of node v0.6.12. It is experimental.
Synopsis#
An example of a web server written with Node which responds with 'Hello World':
var http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
}).listen(8124);
console.log('Server running at http://127.0.0.1:8124/');
To run the server, put the code into a file called example.js
and execute
it with the node program
> node example.js
Server running at http://127.0.0.1:8124/
All of the examples in the documentation can be run similarly.
Global Objects#
These objects are available in all modules. Some of these objects aren't actually in the global scope but in the module scope - this will be noted.
global#
- {Object} The global namespace object.
In browsers, the top-level scope is the global scope. That means that in
browsers if you're in the global scope var something
will define a global
variable. In Node this is different. The top-level scope is not the global
scope; var something
inside a Node module will be local to that module.
process#
- {Object}
The process object. See the process object section.
console#
- {Object}
Used to print to stdout and stderr. See the console section.
Class: Buffer#
- {Function}
Used to handle binary data. See the buffer section
require()#
- {Function}
To require modules. See the Modules section. require
isn't actually a
global but rather local to each module.
require.resolve()#
Use the internal require()
machinery to look up the location of a module,
but rather than loading the module, just return the resolved filename.
require.cache#
- Object
Modules are cached in this object when they are required. By deleting a key
value from this object, the next require
will reload the module.
require.extensions#
Stability: 0 - Deprecated
- Object
Instruct require
on how to handle certain file extensions.
Process files with the extension .sjs
as .js
:
require.extensions['.sjs'] = require.extensions['.js'];
Deprecated In the past, this list has been used to load non-JavaScript modules into Node by compiling them on-demand. However, in practice, there are much better ways to do this, such as loading modules via some other Node program, or compiling them to JavaScript ahead of time.
Since the Module system is locked, this feature will probably never go away. However, it may have subtle bugs and complexities that are best left untouched.
__filename#
- {String}
The filename of the code being executed. This is the resolved absolute path of this code file. For a main program this is not necessarily the same filename used in the command line. The value inside a module is the path to that module file.
Example: running node example.js
from /Users/mjr
console.log(__filename);
// /Users/mjr/example.js
__filename
isn't actually a global but rather local to each module.
__dirname#
- {String}
The name of the directory that the currently executing script resides in.
Example: running node example.js
from /Users/mjr
console.log(__dirname);
// /Users/mjr
__dirname
isn't actually a global but rather local to each module.
module#
- {Object}
A reference to the current module. In particular
module.exports
is used for defining what a module exports and makes
available through require()
.
module
isn't actually a global but rather local to each module.
See the module system documentation for more information.
exports#
A reference to the module.exports
that is shorter to type.
See module system documentation for details on when to use exports
and
when to use module.exports
.
exports
isn't actually a global but rather local to each module.
See the module system documentation for more information.
See the module section for more information.
setTimeout(cb, ms)#
Run callback cb
after at least ms
milliseconds. The actual delay depends
on external factors like OS timer granularity and system load.
The timeout must be in the range of 1-2,147,483,647 inclusive. If the value is outside that range, it's changed to 1 millisecond. Broadly speaking, a timer cannot span more than 24.8 days.
Returns an opaque value that represents the timer.
clearTimeout(t)#
Stop a timer that was previously created with setTimeout()
. The callback will
not execute.
setInterval(cb, ms)#
Run callback cb
repeatedly every ms
milliseconds. Note that the actual
interval may vary, depending on external factors like OS timer granularity and
system load. It's never less than ms
but it may be longer.
The interval must be in the range of 1-2,147,483,647 inclusive. If the value is outside that range, it's changed to 1 millisecond. Broadly speaking, a timer cannot span more than 24.8 days.
Returns an opaque value that represents the timer.
clearInterval(t)#
Stop a timer that was previously created with setInterval()
. The callback
will not execute.
The timer functions are global variables. See the timers section.
console#
Stability: 4 - API Frozen
- Object
For printing to stdout and stderr. Similar to the console object functions provided by most web browsers, here the output is sent to stdout or stderr.
The console functions are synchronous when the destination is a terminal or a file (to avoid lost messages in case of premature exit) and asynchronous when it's a pipe (to avoid blocking for long periods of time).
That is, in the following example, stdout is non-blocking while stderr is blocking:
$ node script.js 2> error.log | tee info.log
In daily use, the blocking/non-blocking dichotomy is not something you should worry about unless you log huge amounts of data.
console.log([data], [...])#
Prints to stdout with newline. This function can take multiple arguments in a
printf()
-like way. Example:
console.log('count: %d', count);
If formatting elements are not found in the first string then util.inspect
is used on each argument. See util.format() for more information.
console.info([data], [...])#
Same as console.log
.
console.error([data], [...])#
Same as console.log
but prints to stderr.
console.warn([data], [...])#
Same as console.error
.
console.dir(obj)#
Uses util.inspect
on obj
and prints resulting string to stdout.
console.time(label)#
Mark a time.
console.timeEnd(label)#
Finish timer, record output. Example:
console.time('100-elements');
for (var i = 0; i < 100; i++) {
;
}
console.timeEnd('100-elements');
console.trace(message, [...])#
Print to stderr 'Trace :'
, followed by the formatted message and stack trace
to the current position.
console.assert(value, [message], [...])#
Similar to assert.ok(), but the error message is formatted as
util.format(message...)
.
Timers#
Stability: 5 - Locked
All of the timer functions are globals. You do not need to require()
this module in order to use them.
setTimeout(callback, delay, [arg], [...])#
To schedule execution of a one-time callback
after delay
milliseconds. Returns a
timeoutObject
for possible use with clearTimeout()
. Optionally you can
also pass arguments to the callback.
It is important to note that your callback will probably not be called in exactly
delay
milliseconds - Node.js makes no guarantees about the exact timing of when
the callback will fire, nor of the ordering things will fire in. The callback will
be called as close as possible to the time specified.
clearTimeout(timeoutObject)#
Prevents a timeout from triggering.
setInterval(callback, delay, [arg], [...])#
To schedule the repeated execution of callback
every delay
milliseconds.
Returns a intervalObject
for possible use with clearInterval()
. Optionally
you can also pass arguments to the callback.
clearInterval(intervalObject)#
Stops an interval from triggering.
unref()#
The opaque value returned by setTimeout
and setInterval
also has the method
timer.unref()
which will allow you to create a timer that is active but if
it is the only item left in the event loop won't keep the program running.
If the timer is already unref
d calling unref
again will have no effect.
In the case of setTimeout
when you unref
you create a separate timer that
will wakeup the event loop, creating too many of these may adversely effect
event loop performance -- use wisely.
ref()#
If you had previously unref()
d a timer you can call ref()
to explicitly
request the timer hold the program open. If the timer is already ref
d calling
ref
again will have no effect.
setImmediate(callback, [arg], [...])#
To schedule the "immediate" execution of callback
after I/O events
callbacks and before setTimeout
and setInterval
. Returns an
immediateObject
for possible use with clearImmediate()
. Optionally you
can also pass arguments to the callback.
Immediates are queued in the order created, and are popped off the queue once
per loop iteration. This is different from process.nextTick
which will
execute process.maxTickDepth
queued callbacks per iteration. setImmediate
will yield to the event loop after firing a queued callback to make sure I/O is
not being starved. While order is preserved for execution, other I/O events may
fire between any two scheduled immediate callbacks.
clearImmediate(immediateObject)#
Stops an immediate from triggering.
Modules#
Stability: 5 - Locked
Node has a simple module loading system. In Node, files and modules are in
one-to-one correspondence. As an example, foo.js
loads the module
circle.js
in the same directory.
The contents of foo.js
:
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is '
+ circle.area(4));
The contents of circle.js
:
var PI = Math.PI;
exports.area = function (r) {
return PI * r * r;
};
exports.circumference = function (r) {
return 2 * PI * r;
};
The module circle.js
has exported the functions area()
and
circumference()
. To add functions and objects to the root of your module,
you can add them to the special exports
object.
Variables local to the module will be private, as though the module was wrapped
in a function. In this example the variable PI
is private to circle.js
.
If you want the root of your module's export to be a function (such as a
constructor) or if you want to export a complete object in one assignment
instead of building it one property at a time, assign it to module.exports
instead of exports
.
Below, bar.js
makes use of the square
module, which exports a constructor:
var square = require('./square.js');
var mySquare = square(2);
console.log('The area of my square is ' + mySquare.area());
The square
module is defined in square.js
:
// assigning to exports will not modify module, must use module.exports
module.exports = function(width) {
return {
area: function() {
return width * width;
}
};
}
The module system is implemented in the require("module")
module.
Cycles#
When there are circular require()
calls, a module might not be
done being executed when it is returned.
Consider this situation:
a.js
:
console.log('a starting');
exports.done = false;
var b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');
b.js
:
console.log('b starting');
exports.done = false;
var a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');
main.js
:
console.log('main starting');
var a = require('./a.js');
var b = require('./b.js');
console.log('in main, a.done=%j, b.done=%j', a.done, b.done);
When main.js
loads a.js
, then a.js
in turn loads b.js
. At that
point, b.js
tries to load a.js
. In order to prevent an infinite
loop an unfinished copy of the a.js
exports object is returned to the
b.js
module. b.js
then finishes loading, and its exports
object is
provided to the a.js
module.
By the time main.js
has loaded both modules, they're both finished.
The output of this program would thus be:
$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done=true, b.done=true
If you have cyclic module dependencies in your program, make sure to plan accordingly.
Core Modules#
Node has several modules compiled into the binary. These modules are described in greater detail elsewhere in this documentation.
The core modules are defined in node's source in the lib/
folder.
Core modules are always preferentially loaded if their identifier is
passed to require()
. For instance, require('http')
will always
return the built in HTTP module, even if there is a file by that name.
File Modules#
If the exact filename is not found, then node will attempt to load the
required filename with the added extension of .js
, .json
, and then .node
.
.js
files are interpreted as JavaScript text files, and .json
files are
parsed as JSON text files. .node
files are interpreted as compiled addon
modules loaded with dlopen
.
A module prefixed with '/'
is an absolute path to the file. For
example, require('/home/marco/foo.js')
will load the file at
/home/marco/foo.js
.
A module prefixed with './'
is relative to the file calling require()
.
That is, circle.js
must be in the same directory as foo.js
for
require('./circle')
to find it.
Without a leading '/' or './' to indicate a file, the module is either a
"core module" or is loaded from a node_modules
folder.
If the given path does not exist, require()
will throw an Error with its
code
property set to 'MODULE_NOT_FOUND'
.
Loading from node_modules
Folders#
If the module identifier passed to require()
is not a native module,
and does not begin with '/'
, '../'
, or './'
, then node starts at the
parent directory of the current module, and adds /node_modules
, and
attempts to load the module from that location.
If it is not found there, then it moves to the parent directory, and so on, until the root of the file system is reached.
For example, if the file at '/home/ry/projects/foo.js'
called
require('bar.js')
, then node would look in the following locations, in
this order:
/home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
This allows programs to localize their dependencies, so that they do not clash.
Folders as Modules#
It is convenient to organize programs and libraries into self-contained
directories, and then provide a single entry point to that library.
There are three ways in which a folder may be passed to require()
as
an argument.
The first is to create a package.json
file in the root of the folder,
which specifies a main
module. An example package.json file might
look like this:
{ "name" : "some-library",
"main" : "./lib/some-library.js" }
If this was in a folder at ./some-library
, then
require('./some-library')
would attempt to load
./some-library/lib/some-library.js
.
This is the extent of Node's awareness of package.json files.
If there is no package.json file present in the directory, then node will
attempt to load an index.js
, index.json
, or index.node
file out of that
directory. For example, if there was no package.json file in the above
example, then require('./some-library')
would attempt to load:
./some-library/index.js
./some-library/index.json
./some-library/index.node
Caching#
Modules are cached after the first time they are loaded. This means
(among other things) that every call to require('foo')
will get
exactly the same object returned, if it would resolve to the same file.
Multiple calls to require('foo')
may not cause the module code to be
executed multiple times. This is an important feature. With it,
"partially done" objects can be returned, thus allowing transitive
dependencies to be loaded even when they would cause cycles.
If you want to have a module execute code multiple times, then export a function, and call that function.
Module Caching Caveats#
Modules are cached based on their resolved filename. Since modules may
resolve to a different filename based on the location of the calling
module (loading from node_modules
folders), it is not a guarantee
that require('foo')
will always return the exact same object, if it
would resolve to different files.
The module
Object#
- {Object}
In each module, the module
free variable is a reference to the object
representing the current module. For convenience, module.exports
is
also accessible via the exports
module-global. module
isn't actually
a global but rather local to each module.
module.exports#
- Object
The module.exports
object is created by the Module system. Sometimes this is not
acceptable; many want their module to be an instance of some class. To do this
assign the desired export object to module.exports
. Note that assigning the
desired object to exports
will simply rebind the local exports
variable,
which is probably not what you want to do.
For example suppose we were making a module called a.js
var EventEmitter = require('events').EventEmitter;
module.exports = new EventEmitter();
// Do some work, and after some time emit
// the 'ready' event from the module itself.
setTimeout(function() {
module.exports.emit('ready');
}, 1000);
Then in another file we could do
var a = require('./a');
a.on('ready', function() {
console.log('module a is ready');
});
Note that assignment to module.exports
must be done immediately. It cannot be
done in any callbacks. This does not work:
x.js:
setTimeout(function() {
module.exports = { a: "hello" };
}, 0);
y.js:
var x = require('./x');
console.log(x.a);
exports alias#
The exports
variable that is available within a module starts as a reference
to module.exports
. As with any variable, if you assign a new value to it, it
is no longer bound to the previous value.
To illustrate the behaviour, imagine this hypothetical implementation of
require()
:
function require(...) {
// ...
function (module, exports) {
// Your module code here
exports = some_func; // re-assigns exports, exports is no longer
// a shortcut, and nothing is exported.
module.exports = some_func; // makes your module export 0
} (module, module.exports);
return module;
}
As a guideline, if the relationship between exports
and module.exports
seems like magic to you, ignore exports
and only use module.exports
.
module.require(id)#
id
String- Return: Object
module.exports
from the resolved module
The module.require
method provides a way to load a module as if
require()
was called from the original module.
Note that in order to do this, you must get a reference to the module
object. Since require()
returns the module.exports
, and the module
is
typically only available within a specific module's code, it must be
explicitly exported in order to be used.
module.id#
- String
The identifier for the module. Typically this is the fully resolved filename.
module.filename#
- String
The fully resolved filename to the module.
module.loaded#
- Boolean
Whether or not the module is done loading, or is in the process of loading.
module.parent#
- Module Object
The module that required this one.
module.children#
- Array
The module objects required by this one.
All Together...#
To get the exact filename that will be loaded when require()
is called, use
the require.resolve()
function.
Putting together all of the above, here is the high-level algorithm in pseudocode of what require.resolve does:
require(X) from module at path Y
1. If X is a core module,
a. return the core module
b. STOP
2. If X begins with './' or '/' or '../'
a. LOAD_AS_FILE(Y + X)
b. LOAD_AS_DIRECTORY(Y + X)
3. LOAD_NODE_MODULES(X, dirname(Y))
4. THROW "not found"
LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text. STOP
2. If X.js is a file, load X.js as JavaScript text. STOP
3. If X.json is a file, parse X.json to a JavaScript Object. STOP
4. If X.node is a file, load X.node as binary addon. STOP
LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
a. Parse X/package.json, and look for "main" field.
b. let M = X + (json main field)
c. LOAD_AS_FILE(M)
2. If X/index.js is a file, load X/index.js as JavaScript text. STOP
3. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
4. If X/index.node is a file, load X/index.node as binary addon. STOP
LOAD_NODE_MODULES(X, START)
1. let DIRS=NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
a. LOAD_AS_FILE(DIR/X)
b. LOAD_AS_DIRECTORY(DIR/X)
NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = []
4. while I >= 0,
a. if PARTS[I] = "node_modules" CONTINUE
c. DIR = path join(PARTS[0 .. I] + "node_modules")
b. DIRS = DIRS + DIR
c. let I = I - 1
5. return DIRS
Loading from the global folders#
If the NODE_PATH
environment variable is set to a colon-delimited list
of absolute paths, then node will search those paths for modules if they
are not found elsewhere. (Note: On Windows, NODE_PATH
is delimited by
semicolons instead of colons.)
Additionally, node will search in the following locations:
- 1:
$HOME/.node_modules
- 2:
$HOME/.node_libraries
- 3:
$PREFIX/lib/node
Where $HOME
is the user's home directory, and $PREFIX
is node's
configured node_prefix
.
These are mostly for historic reasons. You are highly encouraged to
place your dependencies locally in node_modules
folders. They will be
loaded faster, and more reliably.
Accessing the main module#
When a file is run directly from Node, require.main
is set to its
module
. That means that you can determine whether a file has been run
directly by testing
require.main === module
For a file foo.js
, this will be true
if run via node foo.js
, but
false
if run by require('./foo')
.
Because module
provides a filename
property (normally equivalent to
__filename
), the entry point of the current application can be obtained
by checking require.main.filename
.
Addenda: Package Manager Tips#
The semantics of Node's require()
function were designed to be general
enough to support a number of sane directory structures. Package manager
programs such as dpkg
, rpm
, and npm
will hopefully find it possible to
build native packages from Node modules without modification.
Below we give a suggested directory structure that could work:
Let's say that we wanted to have the folder at
/usr/lib/node/<some-package>/<some-version>
hold the contents of a
specific version of a package.
Packages can depend on one another. In order to install package foo
, you
may have to install a specific version of package bar
. The bar
package
may itself have dependencies, and in some cases, these dependencies may even
collide or form cycles.
Since Node looks up the realpath
of any modules it loads (that is,
resolves symlinks), and then looks for their dependencies in the
node_modules
folders as described above, this situation is very simple to
resolve with the following architecture:
/usr/lib/node/foo/1.2.3/
- Contents of thefoo
package, version 1.2.3./usr/lib/node/bar/4.3.2/
- Contents of thebar
package thatfoo
depends on./usr/lib/node/foo/1.2.3/node_modules/bar
- Symbolic link to/usr/lib/node/bar/4.3.2/
./usr/lib/node/bar/4.3.2/node_modules/*
- Symbolic links to the packages thatbar
depends on.
Thus, even if a cycle is encountered, or if there are dependency conflicts, every module will be able to get a version of its dependency that it can use.
When the code in the foo
package does require('bar')
, it will get the
version that is symlinked into /usr/lib/node/foo/1.2.3/node_modules/bar
.
Then, when the code in the bar
package calls require('quux')
, it'll get
the version that is symlinked into
/usr/lib/node/bar/4.3.2/node_modules/quux
.
Furthermore, to make the module lookup process even more optimal, rather
than putting packages directly in /usr/lib/node
, we could put them in
/usr/lib/node_modules/<name>/<version>
. Then node will not bother
looking for missing dependencies in /usr/node_modules
or /node_modules
.
In order to make modules available to the node REPL, it might be useful to
also add the /usr/lib/node_modules
folder to the $NODE_PATH
environment
variable. Since the module lookups using node_modules
folders are all
relative, and based on the real path of the files making the calls to
require()
, the packages themselves can be anywhere.
Addons#
Addons are dynamically linked shared objects. They can provide glue to C and C++ libraries. The API (at the moment) is rather complex, involving knowledge of several libraries:
V8 JavaScript, a C++ library. Used for interfacing with JavaScript: creating objects, calling functions, etc. Documented mostly in the
v8.h
header file (deps/v8/include/v8.h
in the Node source tree), which is also available online.libuv, C event loop library. Anytime one needs to wait for a file descriptor to become readable, wait for a timer, or wait for a signal to be received one will need to interface with libuv. That is, if you perform any I/O, libuv will need to be used.
Internal Node libraries. Most importantly is the
node::ObjectWrap
class which you will likely want to derive from.Others. Look in
deps/
for what else is available.
Node statically compiles all its dependencies into the executable. When compiling your module, you don't need to worry about linking to any of these libraries.
All of the following examples are available for download and may be used as a starting-point for your own Addon.
Hello world#
To get started let's make a small Addon which is the C++ equivalent of the following JavaScript code:
module.exports.hello = function() { return 'world'; };
First we create a file hello.cc
:
#include <node.h>
#include <v8.h>
using namespace v8;
Handle<Value> Method(const Arguments& args) {
HandleScope scope;
return scope.Close(String::New("world"));
}
void init(Handle<Object> exports) {
exports->Set(String::NewSymbol("hello"),
FunctionTemplate::New(Method)->GetFunction());
}
NODE_MODULE(hello, init)
Note that all Node addons must export an initialization function:
void Initialize (Handle<Object> exports);
NODE_MODULE(module_name, Initialize)
There is no semi-colon after NODE_MODULE
as it's not a function (see node.h
).
The module_name
needs to match the filename of the final binary (minus the
.node suffix).
The source code needs to be built into hello.node
, the binary Addon. To
do this we create a file called binding.gyp
which describes the configuration
to build your module in a JSON-like format. This file gets compiled by
node-gyp.
{
"targets": [
{
"target_name": "hello",
"sources": [ "hello.cc" ]
}
]
}
The next step is to generate the appropriate project build files for the
current platform. Use node-gyp configure
for that.
Now you will have either a Makefile
(on Unix platforms) or a vcxproj
file
(on Windows) in the build/
directory. Next invoke the node-gyp build
command.
Now you have your compiled .node
bindings file! The compiled bindings end up
in build/Release/
.
You can now use the binary addon in a Node project hello.js
by pointing require
to
the recently built hello.node
module:
var addon = require('./build/Release/hello');
console.log(addon.hello()); // 'world'
Please see patterns below for further information or
https://github.com/arturadib/node-qt for an example in production.
Addon patterns#
Below are some addon patterns to help you get started. Consult the online v8 reference for help with the various v8 calls, and v8's Embedder's Guide for an explanation of several concepts used such as handles, scopes, function templates, etc.
In order to use these examples you need to compile them using node-gyp
.
Create the following binding.gyp
file:
{
"targets": [
{
"target_name": "addon",
"sources": [ "addon.cc" ]
}
]
}
In cases where there is more than one .cc
file, simply add the file name to the
sources
array, e.g.:
"sources": ["addon.cc", "myexample.cc"]
Now that you have your binding.gyp
ready, you can configure and build the
addon:
$ node-gyp configure build
Function arguments#
The following pattern illustrates how to read arguments from JavaScript
function calls and return a result. This is the main and only needed source
addon.cc
:
#define BUILDING_NODE_EXTENSION
#include <node.h>
using namespace v8;
Handle<Value> Add(const Arguments& args) {
HandleScope scope;
if (args.Length() < 2) {
ThrowException(Exception::TypeError(String::New("Wrong number of arguments")));
return scope.Close(Undefined());
}
if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
ThrowException(Exception::TypeError(String::New("Wrong arguments")));
return scope.Close(Undefined());
}
Local<Number> num = Number::New(args[0]->NumberValue() +
args[1]->NumberValue());
return scope.Close(num);
}
void Init(Handle<Object> exports) {
exports->Set(String::NewSymbol("add"),
FunctionTemplate::New(Add)->GetFunction());
}
NODE_MODULE(addon, Init)
You can test it with the following JavaScript snippet:
var addon = require('./build/Release/addon');
console.log( 'This should be eight:', addon.add(3,5) );
Callbacks#
You can pass JavaScript functions to a C++ function and execute them from
there. Here's addon.cc
:
#define BUILDING_NODE_EXTENSION
#include <node.h>
using namespace v8;
Handle<Value> RunCallback(const Arguments& args) {
HandleScope scope;
Local<Function> cb = Local<Function>::Cast(args[0]);
const unsigned argc = 1;
Local<Value> argv[argc] = { Local<Value>::New(String::New("hello world")) };
cb->Call(Context::GetCurrent()->Global(), argc, argv);
return scope.Close(Undefined());
}
void Init(Handle<Object> exports, Handle<Object> module) {
module->Set(String::NewSymbol("exports"),
FunctionTemplate::New(RunCallback)->GetFunction());
}
NODE_MODULE(addon, Init)
Note that this example uses a two-argument form of Init()
that receives
the full module
object as the second argument. This allows the addon
to completely overwrite exports
with a single function instead of
adding the function as a property of exports
.
To test it run the following JavaScript snippet:
var addon = require('./build/Release/addon');
addon(function(msg){
console.log(msg); // 'hello world'
});
Object factory#
You can create and return new objects from within a C++ function with this
addon.cc
pattern, which returns an object with property msg
that echoes
the string passed to createObject()
:
#define BUILDING_NODE_EXTENSION
#include <node.h>
using namespace v8;
Handle<Value> CreateObject(const Arguments& args) {
HandleScope scope;
Local<Object> obj = Object::New();
obj->Set(String::NewSymbol("msg"), args[0]->ToString());
return scope.Close(obj);
}
void Init(Handle<Object> exports, Handle<Object> module) {
module->Set(String::NewSymbol("exports"),
FunctionTemplate::New(CreateObject)->GetFunction());
}
NODE_MODULE(addon, Init)
To test it in JavaScript:
var addon = require('./build/Release/addon');
var obj1 = addon('hello');
var obj2 = addon('world');
console.log(obj1.msg+' '+obj2.msg); // 'hello world'
Function factory#
This pattern illustrates how to create and return a JavaScript function that wraps a C++ function:
#define BUILDING_NODE_EXTENSION
#include <node.h>
using namespace v8;
Handle<Value> MyFunction(const Arguments& args) {
HandleScope scope;
return scope.Close(String::New("hello world"));
}
Handle<Value> CreateFunction(const Arguments& args) {
HandleScope scope;
Local<FunctionTemplate> tpl = FunctionTemplate::New(MyFunction);
Local<Function> fn = tpl->GetFunction();
fn->SetName(String::NewSymbol("theFunction")); // omit this to make it anonymous
return scope.Close(fn);
}
void Init(Handle<Object> exports, Handle<Object> module) {
module->Set(String::NewSymbol("exports"),
FunctionTemplate::New(CreateFunction)->GetFunction());
}
NODE_MODULE(addon, Init)
To test:
var addon = require('./build/Release/addon');
var fn = addon();
console.log(fn()); // 'hello world'
Wrapping C++ objects#
Here we will create a wrapper for a C++ object/class MyObject
that can be
instantiated in JavaScript through the new
operator. First prepare the main
module addon.cc
:
#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
using namespace v8;
void InitAll(Handle<Object> exports) {
MyObject::Init(exports);
}
NODE_MODULE(addon, InitAll)
Then in myobject.h
make your wrapper inherit from node::ObjectWrap
:
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <node.h>
class MyObject : public node::ObjectWrap {
public:
static void Init(v8::Handle<v8::Object> exports);
private:
explicit MyObject(double value = 0);
~MyObject();
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
static v8::Persistent<v8::Function> constructor;
double value_;
};
#endif
And in myobject.cc
implement the various methods that you want to expose.
Here we expose the method plusOne
by adding it to the constructor's
prototype:
#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
using namespace v8;
Persistent<Function> MyObject::constructor;
MyObject::MyObject(double value) : value_(value) {
}
MyObject::~MyObject() {
}
void MyObject::Init(Handle<Object> exports) {
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
FunctionTemplate::New(PlusOne)->GetFunction());
constructor = Persistent<Function>::New(tpl->GetFunction());
exports->Set(String::NewSymbol("MyObject"), constructor);
}
Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
if (args.IsConstructCall()) {
// Invoked as constructor: `new MyObject(...)`
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
MyObject* obj = new MyObject(value);
obj->Wrap(args.This());
return args.This();
} else {
// Invoked as plain function `MyObject(...)`, turn into construct call.
const int argc = 1;
Local<Value> argv[argc] = { args[0] };
return scope.Close(constructor->NewInstance(argc, argv));
}
}
Handle<Value> MyObject::PlusOne(const Arguments& args) {
HandleScope scope;
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
obj->value_ += 1;
return scope.Close(Number::New(obj->value_));
}
Test it with:
var addon = require('./build/Release/addon');
var obj = new addon.MyObject(10);
console.log( obj.plusOne() ); // 11
console.log( obj.plusOne() ); // 12
console.log( obj.plusOne() ); // 13
Factory of wrapped objects#
This is useful when you want to be able to create native objects without
explicitly instantiating them with the new
operator in JavaScript, e.g.
var obj = addon.createObject();
// instead of:
// var obj = new addon.Object();
Let's register our createObject
method in addon.cc
:
#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
using namespace v8;
Handle<Value> CreateObject(const Arguments& args) {
HandleScope scope;
return scope.Close(MyObject::NewInstance(args));
}
void InitAll(Handle<Object> exports, Handle<Object> module) {
MyObject::Init();
module->Set(String::NewSymbol("exports"),
FunctionTemplate::New(CreateObject)->GetFunction());
}
NODE_MODULE(addon, InitAll)
In myobject.h
we now introduce the static method NewInstance
that takes
care of instantiating the object (i.e. it does the job of new
in JavaScript):
#define BUILDING_NODE_EXTENSION
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <node.h>
class MyObject : public node::ObjectWrap {
public:
static void Init();
static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
private:
explicit MyObject(double value = 0);
~MyObject();
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
static v8::Persistent<v8::Function> constructor;
double value_;
};
#endif
The implementation is similar to the above in myobject.cc
:
#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
using namespace v8;
Persistent<Function> MyObject::constructor;
MyObject::MyObject(double value) : value_(value) {
}
MyObject::~MyObject() {
}
void MyObject::Init() {
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
FunctionTemplate::New(PlusOne)->GetFunction());
constructor = Persistent<Function>::New(tpl->GetFunction());
}
Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
if (args.IsConstructCall()) {
// Invoked as constructor: `new MyObject(...)`
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
MyObject* obj = new MyObject(value);
obj->Wrap(args.This());
return args.This();
} else {
// Invoked as plain function `MyObject(...)`, turn into construct call.
const int argc = 1;
Local<Value> argv[argc] = { args[0] };
return scope.Close(constructor->NewInstance(argc, argv));
}
}
Handle<Value> MyObject::NewInstance(const Arguments& args) {
HandleScope scope;
const unsigned argc = 1;
Handle<Value> argv[argc] = { args[0] };
Local<Object> instance = constructor->NewInstance(argc, argv);
return scope.Close(instance);
}
Handle<Value> MyObject::PlusOne(const Arguments& args) {
HandleScope scope;
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
obj->value_ += 1;
return scope.Close(Number::New(obj->value_));
}
Test it with:
var createObject = require('./build/Release/addon');
var obj = createObject(10);
console.log( obj.plusOne() ); // 11
console.log( obj.plusOne() ); // 12
console.log( obj.plusOne() ); // 13
var obj2 = createObject(20);
console.log( obj2.plusOne() ); // 21
console.log( obj2.plusOne() ); // 22
console.log( obj2.plusOne() ); // 23
Passing wrapped objects around#
In addition to wrapping and returning C++ objects, you can pass them around
by unwrapping them with Node's node::ObjectWrap::Unwrap
helper function.
In the following addon.cc
we introduce a function add()
that can take on two
MyObject
objects:
#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
using namespace v8;
Handle<Value> CreateObject(const Arguments& args) {
HandleScope scope;
return scope.Close(MyObject::NewInstance(args));
}
Handle<Value> Add(const Arguments& args) {
HandleScope scope;
MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>(
args[0]->ToObject());
MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(
args[1]->ToObject());
double sum = obj1->Value() + obj2->Value();
return scope.Close(Number::New(sum));
}
void InitAll(Handle<Object> exports) {
MyObject::Init();
exports->Set(String::NewSymbol("createObject"),
FunctionTemplate::New(CreateObject)->GetFunction());
exports->Set(String::NewSymbol("add"),
FunctionTemplate::New(Add)->GetFunction());
}
NODE_MODULE(addon, InitAll)
To make things interesting we introduce a public method in myobject.h
so we
can probe private values after unwrapping the object:
#define BUILDING_NODE_EXTENSION
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <node.h>
class MyObject : public node::ObjectWrap {
public:
static void Init();
static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
double Value() const { return value_; }
private:
explicit MyObject(double value = 0);
~MyObject();
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Persistent<v8::Function> constructor;
double value_;
};
#endif
The implementation of myobject.cc
is similar as before:
#define BUILDING_NODE_EXTENSION
#include <node.h>
#include "myobject.h"
using namespace v8;
Persistent<Function> MyObject::constructor;
MyObject::MyObject(double value) : value_(value) {
}
MyObject::~MyObject() {
}
void MyObject::Init() {
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
constructor = Persistent<Function>::New(tpl->GetFunction());
}
Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
if (args.IsConstructCall()) {
// Invoked as constructor: `new MyObject(...)`
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
MyObject* obj = new MyObject(value);
obj->Wrap(args.This());
return args.This();
} else {
// Invoked as plain function `MyObject(...)`, turn into construct call.
const int argc = 1;
Local<Value> argv[argc] = { args[0] };
return scope.Close(constructor->NewInstance(argc, argv));
}
}
Handle<Value> MyObject::NewInstance(const Arguments& args) {
HandleScope scope;
const unsigned argc = 1;
Handle<Value> argv[argc] = { args[0] };
Local<Object> instance = constructor->NewInstance(argc, argv);
return scope.Close(instance);
}
Test it with:
var addon = require('./build/Release/addon');
var obj1 = addon.createObject(10);
var obj2 = addon.createObject(20);
var result = addon.add(obj1, obj2);
console.log(result); // 30
process#
The process
object is a global object and can be accessed from anywhere.
It is an instance of EventEmitter.
Event: 'exit'#
Emitted when the process is about to exit. There is no way to prevent the
exiting of the event loop at this point, and once all exit
listeners have
finished running the process will exit. Therefore you must only perform
synchronous operations in this handler. This is a good hook to perform
checks on the module's state (like for unit tests). The callback takes one
argument, the code the process is exiting with.
Example of listening for exit
:
process.on('exit', function(code) {
// do *NOT* do this
setTimeout(function() {
console.log('This will not run');
}, 0);
console.log('About to exit with code:', code);
});
Event: 'uncaughtException'#
Emitted when an exception bubbles all the way back to the event loop. If a listener is added for this exception, the default action (which is to print a stack trace and exit) will not occur.
Example of listening for uncaughtException
:
process.on('uncaughtException', function(err) {
console.log('Caught exception: ' + err);
});
setTimeout(function() {
console.log('This will still run.');
}, 500);
// Intentionally cause an exception, but don't catch it.
nonexistentFunc();
console.log('This will not run.');
Note that uncaughtException
is a very crude mechanism for exception
handling and may be removed in the future.
Don't use it, use domains instead. If you do use it, restart your application after every unhandled exception!
Do not use it as the node.js equivalent of On Error Resume Next
. An
unhandled exception means your application - and by extension node.js itself -
is in an undefined state. Blindly resuming means anything could happen.
Think of resuming as pulling the power cord when you are upgrading your system. Nine out of ten times nothing happens - but the 10th time, your system is bust.
You have been warned.
Signal Events#
Emitted when the processes receives a signal. See sigaction(2) for a list of standard POSIX signal names such as SIGINT, SIGHUP, etc.
Example of listening for SIGINT
:
// Start reading from stdin so we don't exit.
process.stdin.resume();
process.on('SIGINT', function() {
console.log('Got SIGINT. Press Control-D to exit.');
});
An easy way to send the SIGINT
signal is with Control-C
in most terminal
programs.
Note:
SIGUSR1
is reserved by node.js to start the debugger. It's possible to install a listener but that won't stop the debugger from starting.SIGTERM
andSIGINT
have default handlers on non-Windows platforms that resets the terminal mode before exiting with code128 + signal number
. If one of these signals has a listener installed, its default behaviour will be removed (node will no longer exit).SIGPIPE
is ignored by default, it can have a listener installed.SIGHUP
is generated on Windows when the console window is closed, and on other platforms under various similar conditions, see signal(7). It can have a listener installed, however node will be unconditionally terminated by Windows about 10 seconds later. On non-Windows platforms, the default behaviour ofSIGHUP
is to terminate node, but once a listener has been installed its default behaviour will be removed.SIGTERM
is not supported on Windows, it can be listened on.SIGINT
from the terminal is supported on all platforms, and can usually be generated withCTRL+C
(though this may be configurable). It is not generated when terminal raw mode is enabled.SIGBREAK
is delivered on Windows whenCTRL+BREAK
is pressed, on non-Windows platforms it can be listened on, but there is no way to send or generate it.SIGWINCH
is delivered when the console has been resized. On Windows, this will only happen on write to the console when the cursor is being moved, or when a readable tty is used in raw mode.SIGKILL
cannot have a listener installed, it will unconditionally terminate node on all platforms.SIGSTOP
cannot have a listener installed.
Note that Windows does not support sending Signals, but node offers some
emulation with process.kill()
, and child_process.kill()
:
- Sending signal 0
can be used to search for the existence of a process
- Sending SIGINT
, SIGTERM
, and SIGKILL
cause the unconditional exit of the
target process.
process.stdout#
A Writable Stream
to stdout
(on fd 1
).
Example: the definition of console.log
console.log = function(d) {
process.stdout.write(d + '\n');
};
process.stderr
and process.stdout
are unlike other streams in Node in
that writes to them are usually blocking.
- They are blocking in the case that they refer to regular files or TTY file descriptors.
- In the case they refer to pipes:
- They are blocking in Linux/Unix.
- They are non-blocking like other streams in Windows.
To check if Node is being run in a TTY context, read the isTTY
property
on process.stderr
, process.stdout
, or process.stdin
:
$ node -p "Boolean(process.stdin.isTTY)"
true
$ echo "foo" | node -p "Boolean(process.stdin.isTTY)"
false
$ node -p "Boolean(process.stdout.isTTY)"
true
$ node -p "Boolean(process.stdout.isTTY)" | cat
false
See the tty docs for more information.
process.stderr#
A writable stream to stderr (on fd 2
).
process.stderr
and process.stdout
are unlike other streams in Node in
that writes to them are usually blocking.
- They are blocking in the case that they refer to regular files or TTY file descriptors.
- In the case they refer to pipes:
- They are blocking in Linux/Unix.
- They are non-blocking like other streams in Windows.
process.stdin#
A Readable Stream
for stdin (on fd 0
).
Example of opening standard input and listening for both events:
process.stdin.setEncoding('utf8');
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null) {
process.stdout.write('data: ' + chunk);
}
});
process.stdin.on('end', function() {
process.stdout.write('end');
});
As a Stream, process.stdin
can also be used in "old" mode that is compatible
with scripts written for node prior v0.10.
For more information see
Stream compatibility.
In "old" Streams mode the stdin stream is paused by default, so one
must call process.stdin.resume()
to read from it. Note also that calling
process.stdin.resume()
itself would switch stream to "old" mode.
If you are starting a new project you should prefer a more recent "new" Streams mode over "old" one.
process.argv#
An array containing the command line arguments. The first element will be 'node', the second element will be the name of the JavaScript file. The next elements will be any additional command line arguments.
// print process.argv
process.argv.forEach(function(val, index, array) {
console.log(index + ': ' + val);
});
This will generate:
$ node process-2.js one two=three four
0: node
1: /Users/mjr/work/node/process-2.js
2: one
3: two=three
4: four
process.execPath#
This is the absolute pathname of the executable that started the process.
Example:
/usr/local/bin/node
process.execArgv#
This is the set of node-specific command line options from the
executable that started the process. These options do not show up in
process.argv
, and do not include the node executable, the name of
the script, or any options following the script name. These options
are useful in order to spawn child processes with the same execution
environment as the parent.
Example:
$ node --harmony script.js --version
results in process.execArgv:
['--harmony']
and process.argv:
['/usr/local/bin/node', 'script.js', '--version']
process.abort()#
This causes node to emit an abort. This will cause node to exit and generate a core file.
process.chdir(directory)#
Changes the current working directory of the process or throws an exception if that fails.
console.log('Starting directory: ' + process.cwd());
try {
process.chdir('/tmp');
console.log('New directory: ' + process.cwd());
}
catch (err) {
console.log('chdir: ' + err);
}
process.cwd()#
Returns the current working directory of the process.
console.log('Current directory: ' + process.cwd());
process.env#
An object containing the user environment. See environ(7).
An example of this object looks like:
{ TERM: 'xterm-256color',
SHELL: '/usr/local/bin/bash',
USER: 'maciej',
PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
PWD: '/Users/maciej',
EDITOR: 'vim',
SHLVL: '1',
HOME: '/Users/maciej',
LOGNAME: 'maciej',
_: '/usr/local/bin/node' }
You can write to this object, but changes won't be reflected outside of your process. That means that the following won't work:
node -e 'process.env.foo = "bar"' && echo $foo
But this will:
process.env.foo = 'bar';
console.log(process.env.foo);
process.exit([code])#
Ends the process with the specified code
. If omitted, exit uses the
'success' code 0
.
To exit with a 'failure' code:
process.exit(1);
The shell that executed node should see the exit code as 1.
process.getgid()#
Note: this function is only available on POSIX platforms (i.e. not Windows)
Gets the group identity of the process. (See getgid(2).) This is the numerical group id, not the group name.
if (process.getgid) {
console.log('Current gid: ' + process.getgid());
}
process.setgid(id)#
Note: this function is only available on POSIX platforms (i.e. not Windows)
Sets the group identity of the process. (See setgid(2).) This accepts either a numerical ID or a groupname string. If a groupname is specified, this method blocks while resolving it to a numerical ID.
if (process.getgid && process.setgid) {
console.log('Current gid: ' + process.getgid());
try {
process.setgid(501);
console.log('New gid: ' + process.getgid());
}
catch (err) {
console.log('Failed to set gid: ' + err);
}
}
process.getuid()#
Note: this function is only available on POSIX platforms (i.e. not Windows)
Gets the user identity of the process. (See getuid(2).) This is the numerical userid, not the username.
if (process.getuid) {
console.log('Current uid: ' + process.getuid());
}
process.setuid(id)#
Note: this function is only available on POSIX platforms (i.e. not Windows)
Sets the user identity of the process. (See setuid(2).) This accepts either a numerical ID or a username string. If a username is specified, this method blocks while resolving it to a numerical ID.
if (process.getuid && process.setuid) {
console.log('Current uid: ' + process.getuid());
try {
process.setuid(501);
console.log('New uid: ' + process.getuid());
}
catch (err) {
console.log('Failed to set uid: ' + err);
}
}
process.getgroups()#
Note: this function is only available on POSIX platforms (i.e. not Windows)
Returns an array with the supplementary group IDs. POSIX leaves it unspecified if the effective group ID is included but node.js ensures it always is.
process.setgroups(groups)#
Note: this function is only available on POSIX platforms (i.e. not Windows)
Sets the supplementary group IDs. This is a privileged operation, meaning you need to be root or have the CAP_SETGID capability.
The list can contain group IDs, group names or both.
process.initgroups(user, extra_group)#
Note: this function is only available on POSIX platforms (i.e. not Windows)
Reads /etc/group and initializes the group access list, using all groups of which the user is a member. This is a privileged operation, meaning you need to be root or have the CAP_SETGID capability.
user
is a user name or user ID. extra_group
is a group name or group ID.
Some care needs to be taken when dropping privileges. Example:
console.log(process.getgroups()); // [ 0 ]
process.initgroups('bnoordhuis', 1000); // switch user
console.log(process.getgroups()); // [ 27, 30, 46, 1000, 0 ]
process.setgid(1000); // drop root gid
console.log(process.getgroups()); // [ 27, 30, 46, 1000 ]
process.version#
A compiled-in property that exposes NODE_VERSION
.
console.log('Version: ' + process.version);
process.versions#
A property exposing version strings of node and its dependencies.
console.log(process.versions);
Will print something like:
{ http_parser: '1.0',
node: '0.10.4',
v8: '3.14.5.8',
ares: '1.9.0-DEV',
uv: '0.10.3',
zlib: '1.2.3',
modules: '11',
openssl: '1.0.1e' }
process.config#
An Object containing the JavaScript representation of the configure options
that were used to compile the current node executable. This is the same as
the "config.gypi" file that was produced when running the ./configure
script.
An example of the possible output looks like:
{ target_defaults:
{ cflags: [],
default_configuration: 'Release',
defines: [],
include_dirs: [],
libraries: [] },
variables:
{ host_arch: 'x64',
node_install_npm: 'true',
node_prefix: '',
node_shared_cares: 'false',
node_shared_http_parser: 'false',
node_shared_libuv: 'false',
node_shared_v8: 'false',
node_shared_zlib: 'false',
node_use_dtrace: 'false',
node_use_openssl: 'true',
node_shared_openssl: 'false',
strict_aliasing: 'true',
target_arch: 'x64',
v8_use_snapshot: 'true' } }
process.kill(pid, [signal])#
Send a signal to a process. pid
is the process id and signal
is the
string describing the signal to send. Signal names are strings like
'SIGINT' or 'SIGHUP'. If omitted, the signal will be 'SIGTERM'.
See Signal Events and kill(2) for more information.
Will throw an error if target does not exist, and as a special case, a signal of
0
can be used to test for the existence of a process.
Note that just because the name of this function is process.kill
, it is
really just a signal sender, like the kill
system call. The signal sent
may do something other than kill the target process.
Example of sending a signal to yourself:
process.on('SIGHUP', function() {
console.log('Got SIGHUP signal.');
});
setTimeout(function() {
console.log('Exiting.');
process.exit(0);
}, 100);
process.kill(process.pid, 'SIGHUP');
Note: When SIGUSR1 is received by Node.js it starts the debugger, see Signal Events.
process.pid#
The PID of the process.
console.log('This process is pid ' + process.pid);
process.title#
Getter/setter to set what is displayed in 'ps'.
When used as a setter, the maximum length is platform-specific and probably short.
On Linux and OS X, it's limited to the size of the binary name plus the length of the command line arguments because it overwrites the argv memory.
v0.8 allowed for longer process title strings by also overwriting the environ memory but that was potentially insecure/confusing in some (rather obscure) cases.
process.arch#
What processor architecture you're running on: 'arm'
, 'ia32'
, or 'x64'
.
console.log('This processor architecture is ' + process.arch);
process.platform#
What platform you're running on:
'darwin'
, 'freebsd'
, 'linux'
, 'sunos'
or 'win32'
console.log('This platform is ' + process.platform);
process.memoryUsage()#
Returns an object describing the memory usage of the Node process measured in bytes.
var util = require('util');
console.log(util.inspect(process.memoryUsage()));
This will generate:
{ rss: 4935680,
heapTotal: 1826816,
heapUsed: 650472 }
heapTotal
and heapUsed
refer to V8's memory usage.
process.nextTick(callback)#
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. It typically runs before any other I/O events fire, but there
are some exceptions. See process.maxTickDepth
below.
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])#
Sets or reads the process's file mode creation mask. Child processes inherit
the mask from the parent process. Returns the old mask if mask
argument is
given, otherwise returns the current mask.
var oldmask, newmask = 0644;
oldmask = process.umask(newmask);
console.log('Changed umask from: ' + oldmask.toString(8) +
' to ' + newmask.toString(8));
process.uptime()#
Number of seconds Node has been running.
process.hrtime()#
Returns the current high-resolution real time in a [seconds, nanoseconds]
tuple Array. It is relative to an arbitrary time in the past. It is not
related to the time of day and therefore not subject to clock drift. The
primary use is for measuring performance between intervals.
You may pass in the result of a previous call to process.hrtime()
to get
a diff reading, useful for benchmarks and measuring intervals:
var time = process.hrtime();
// [ 1800216, 25 ]
setTimeout(function() {
var diff = process.hrtime(time);
// [ 1, 552 ]
console.log('benchmark took %d nanoseconds', diff[0] * 1e9 + diff[1]);
// benchmark took 1000000527 nanoseconds
}, 1000);
util#
Stability: 4 - API Frozen
These functions are in the module 'util'
. Use require('util')
to access
them.
util.format(format, [...])#
Returns a formatted string using the first argument as a printf
-like format.
The first argument is a string that contains zero or more placeholders. Each placeholder is replaced with the converted value from its corresponding argument. Supported placeholders are:
%s
- String.%d
- Number (both integer and float).%j
- JSON.%
- single percent sign ('%'
). This does not consume an argument.
If the placeholder does not have a corresponding argument, the placeholder is not replaced.
util.format('%s:%s', 'foo'); // 'foo:%s'
If there are more arguments than placeholders, the extra arguments are
converted to strings with util.inspect()
and these strings are concatenated,
delimited by a space.
util.format('%s:%s', 'foo', 'bar', 'baz'); // 'foo:bar baz'
If the first argument is not a format string then util.format()
returns
a string that is the concatenation of all its arguments separated by spaces.
Each argument is converted to a string with util.inspect()
.
util.format(1, 2, 3); // '1 2 3'
util.debug(string)#
A synchronous output function. Will block the process and
output string
immediately to stderr
.
require('util').debug('message on stderr');
util.error([...])#
Same as util.debug()
except this will output all arguments immediately to
stderr
.
util.puts([...])#
A synchronous output function. Will block the process and output all arguments
to stdout
with newlines after each argument.
util.print([...])#
A synchronous output function. Will block the process, cast each argument to a
string then output to stdout
. Does not place newlines after each argument.
util.log(string)#
Output with timestamp on stdout
.
require('util').log('Timestamped message.');
util.inspect(object, [options])#
Return a string representation of object
, which is useful for debugging.
An optional options object may be passed that alters certain aspects of the formatted string:
showHidden
- iftrue
then the object's non-enumerable properties will be shown too. Defaults tofalse
.depth
- tellsinspect
how many times to recurse while formatting the object. This is useful for inspecting large complicated objects. Defaults to2
. To make it recurse indefinitely passnull
.colors
- iftrue
, then the output will be styled with ANSI color codes. Defaults tofalse
. Colors are customizable, see below.customInspect
- iffalse
, then custominspect()
functions defined on the objects being inspected won't be called. Defaults totrue
.
Example of inspecting all properties of the util
object:
var util = require('util');
console.log(util.inspect(util, { showHidden: true, depth: null }));
Customizing util.inspect
colors#
Color output (if enabled) of util.inspect
is customizable globally
via util.inspect.styles
and util.inspect.colors
objects.
util.inspect.styles
is a map assigning each style a color
from util.inspect.colors
.
Highlighted styles and their default values are:
number
(yellow)
boolean
(yellow)
string
(green)
date
(magenta)
regexp
(red)
null
(bold)
undefined
(grey)
special
- only function at this time (cyan)
* name
(intentionally no styling)
Predefined color codes are: white
, grey
, black
, blue
, cyan
,
green
, magenta
, red
and yellow
.
There are also bold
, italic
, underline
and inverse
codes.
Objects also may define their own inspect(depth)
function which util.inspect()
will invoke and use the result of when inspecting the object:
var util = require('util');
var obj = { name: 'nate' };
obj.inspect = function(depth) {
return '{' + this.name + '}';
};
util.inspect(obj);
// "{nate}"
util.isArray(object)#
Returns true
if the given "object" is an Array
. false
otherwise.
var util = require('util');
util.isArray([])
// true
util.isArray(new Array)
// true
util.isArray({})
// false
util.isRegExp(object)#
Returns true
if the given "object" is a RegExp
. false
otherwise.
var util = require('util');
util.isRegExp(/some regexp/)
// true
util.isRegExp(new RegExp('another regexp'))
// true
util.isRegExp({})
// false
util.isDate(object)#
Returns true
if the given "object" is a Date
. false
otherwise.
var util = require('util');
util.isDate(new Date())
// true
util.isDate(Date())
// false (without 'new' returns a String)
util.isDate({})
// false
util.isError(object)#
Returns true
if the given "object" is an Error
. false
otherwise.
var util = require('util');
util.isError(new Error())
// true
util.isError(new TypeError())
// true
util.isError({ name: 'Error', message: 'an error occurred' })
// false
util.pump(readableStream, writableStream, [callback])#
Stability: 0 - Deprecated: Use readableStream.pipe(writableStream)
Read the data from readableStream
and send it to the writableStream
.
When writableStream.write(data)
returns false
readableStream
will be
paused until the drain
event occurs on the writableStream
. callback
gets
an error as its only argument and is called when writableStream
is closed or
when an error occurs.
util.inherits(constructor, superConstructor)#
Inherit the prototype methods from one
constructor
into another. The prototype of constructor
will be set to a new
object created from superConstructor
.
As an additional convenience, superConstructor
will be accessible
through the constructor.super_
property.
var util = require("util");
var events = require("events");
function MyStream() {
events.EventEmitter.call(this);
}
util.inherits(MyStream, events.EventEmitter);
MyStream.prototype.write = function(data) {
this.emit("data", data);
}
var stream = new MyStream();
console.log(stream instanceof events.EventEmitter); // true
console.log(MyStream.super_ === events.EventEmitter); // true
stream.on("data", function(data) {
console.log('Received data: "' + data + '"');
})
stream.write("It works!"); // Received data: "It works!"
Events#
Stability: 4 - API Frozen
Many objects in Node emit events: a net.Server
emits an event each time
a peer connects to it, a fs.readStream
emits an event when the file is
opened. All objects which emit events are instances of events.EventEmitter
.
You can access this module by doing: require("events");
Typically, event names are represented by a camel-cased string, however, there aren't any strict restrictions on that, as any string will be accepted.
Functions can then be attached to objects, to be executed when an event
is emitted. These functions are called listeners. Inside a listener
function, this
refers to the EventEmitter
that the listener was
attached to.
Class: events.EventEmitter#
To access the EventEmitter class, require('events').EventEmitter
.
When an EventEmitter
instance experiences an error, the typical action is
to emit an 'error'
event. Error events are treated as a special case in node.
If there is no listener for it, then the default action is to print a stack
trace and exit the program.
All EventEmitters emit the event 'newListener'
when new listeners are
added and 'removeListener'
when a listener is removed.
emitter.addListener(event, listener)#
emitter.on(event, listener)#
Adds a listener to the end of the listeners array for the specified event
.
No checks are made to see if the listener
has already been added. Multiple
calls passing the same combination of event
and listener
will result in the
listener
being added multiple times.
server.on('connection', function (stream) {
console.log('someone connected!');
});
Returns emitter, so calls can be chained.
emitter.once(event, listener)#
Adds a one time listener for the event. This listener is invoked only the next time the event is fired, after which it is removed.
server.once('connection', function (stream) {
console.log('Ah, we have our first user!');
});
Returns emitter, so calls can be chained.
emitter.removeListener(event, listener)#
Remove a listener from the listener array for the specified event. Caution: changes array indices in the listener array behind the listener.
var callback = function(stream) {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
removeListener
will remove, at most, one instance of a listener from the
listener array. If any single listener has been added multiple times to the
listener array for the specified event
, then removeListener
must be called
multiple times to remove each instance.
Returns emitter, so calls can be chained.
emitter.removeAllListeners([event])#
Removes all listeners, or those of the specified event. It's not a good idea to remove listeners that were added elsewhere in the code, especially when it's on an emitter that you didn't create (e.g. sockets or file streams).
Returns emitter, so calls can be chained.
emitter.setMaxListeners(n)#
By default EventEmitters will print a warning if more than 10 listeners are added for a particular event. This is a useful default which helps finding memory leaks. Obviously not all Emitters should be limited to 10. This function allows that to be increased. Set to zero for unlimited.
emitter.listeners(event)#
Returns an array of listeners for the specified event.
server.on('connection', function (stream) {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection'))); // [ [Function] ]
emitter.emit(event, [arg1], [arg2], [...])#
Execute each of the listeners in order with the supplied arguments.
Returns true
if event had listeners, false
otherwise.
Class Method: EventEmitter.listenerCount(emitter, event)#
Return the number of listeners for a given event.
Event: 'newListener'#
event
String The event namelistener
Function The event handler function
This event is emitted any time a listener is added. When this event is triggered,
the listener may not yet have been added to the array of listeners for the event
.
Event: 'removeListener'#
event
String The event namelistener
Function The event handler function
This event is emitted any time someone removes a listener. When this event is triggered,
the listener may not yet have been removed from the array of listeners for the event
.
Domain#
Stability: 2 - Unstable
Domains provide a way to handle multiple different IO operations as a
single group. If any of the event emitters or callbacks registered to a
domain emit an error
event, or throw an error, then the domain object
will be notified, rather than losing the context of the error in the
process.on('uncaughtException')
handler, or causing the program to
exit immediately with an error code.
Warning: Don't Ignore Errors!#
Domain error handlers are not a substitute for closing down your process when an error occurs.
By the very nature of how throw
works in JavaScript, there is almost
never any way to safely "pick up where you left off", without leaking
references, or creating some other sort of undefined brittle state.
The safest way to respond to a thrown error is to shut down the process. Of course, in a normal web server, you might have many connections open, and it is not reasonable to abruptly shut those down because an error was triggered by someone else.
The better approach is send an error response to the request that triggered the error, while letting the others finish in their normal time, and stop listening for new requests in that worker.
In this way, domain
usage goes hand-in-hand with the cluster module,
since the master process can fork a new worker when a worker
encounters an error. For node programs that scale to multiple
machines, the terminating proxy or service registry can take note of
the failure, and react accordingly.
For example, this is not a good idea:
// XXX WARNING! BAD IDEA!
var d = require('domain').create();
d.on('error', function(er) {
// The error won't crash the process, but what it does is worse!
// Though we've prevented abrupt process restarting, we are leaking
// resources like crazy if this ever happens.
// This is no better than process.on('uncaughtException')!
console.log('error, but oh well', er.message);
});
d.run(function() {
require('http').createServer(function(req, res) {
handleRequest(req, res);
}).listen(PORT);
});
By using the context of a domain, and the resilience of separating our program into multiple worker processes, we can react more appropriately, and handle errors with much greater safety.
// Much better!
var cluster = require('cluster');
var PORT = +process.env.PORT || 1337;
if (cluster.isMaster) {
// In real life, you'd probably use more than just 2 workers,
// and perhaps not put the master and worker in the same file.
//
// You can also of course get a bit fancier about logging, and
// implement whatever custom logic you need to prevent DoS
// attacks and other bad behavior.
//
// See the options in the cluster documentation.
//
// The important thing is that the master does very little,
// increasing our resilience to unexpected errors.
cluster.fork();
cluster.fork();
cluster.on('disconnect', function(worker) {
console.error('disconnect!');
cluster.fork();
});
} else {
// the worker
//
// This is where we put our bugs!
var domain = require('domain');
// See the cluster documentation for more details about using
// worker processes to serve requests. How it works, caveats, etc.
var server = require('http').createServer(function(req, res) {
var d = domain.create();
d.on('error', function(er) {
console.error('error', er.stack);
// Note: we're in dangerous territory!
// By definition, something unexpected occurred,
// which we probably didn't want.
// Anything can happen now! Be very careful!
try {
// make sure we close down within 30 seconds
var killtimer = setTimeout(function() {
process.exit(1);
}, 30000);
// But don't keep the process open just for that!
killtimer.unref();
// stop taking new requests.
server.close();
// Let the master know we're dead. This will trigger a
// 'disconnect' in the cluster master, and then it will fork
// a new worker.
cluster.worker.disconnect();
// try to send an error to the request that triggered the problem
res.statusCode = 500;
res.setHeader('content-type', 'text/plain');
res.end('Oops, there was a problem!\n');
} catch (er2) {
// oh well, not much we can do at this point.
console.error('Error sending 500!', er2.stack);
}
});
// Because req and res were created before this domain existed,
// we need to explicitly add them.
// See the explanation of implicit vs explicit binding below.
d.add(req);
d.add(res);
// Now run the handler function in the domain.
d.run(function() {
handleRequest(req, res);
});
});
server.listen(PORT);
}
// This part isn't important. Just an example routing thing.
// You'd put your fancy application logic here.
function handleRequest(req, res) {
switch(req.url) {
case '/error':
// We do some async stuff, and then...
setTimeout(function() {
// Whoops!
flerb.bark();
});
break;
default:
res.end('ok');
}
}
Additions to Error objects#
Any time an Error object is routed through a domain, a few extra fields are added to it.
error.domain
The domain that first handled the error.error.domainEmitter
The event emitter that emitted an 'error' event with the error object.error.domainBound
The callback function which was bound to the domain, and passed an error as its first argument.error.domainThrown
A boolean indicating whether the error was thrown, emitted, or passed to a bound callback function.
Implicit Binding#
If domains are in use, then all new EventEmitter objects (including Stream objects, requests, responses, etc.) will be implicitly bound to the active domain at the time of their creation.
Additionally, callbacks passed to lowlevel event loop requests (such as to fs.open, or other callback-taking methods) will automatically be bound to the active domain. If they throw, then the domain will catch the error.
In order to prevent excessive memory usage, Domain objects themselves are not implicitly added as children of the active domain. If they were, then it would be too easy to prevent request and response objects from being properly garbage collected.
If you want to nest Domain objects as children of a parent Domain, then you must explicitly add them.
Implicit binding routes thrown errors and 'error'
events to the
Domain's error
event, but does not register the EventEmitter on the
Domain, so domain.dispose()
will not shut down the EventEmitter.
Implicit binding only takes care of thrown errors and 'error'
events.
Explicit Binding#
Sometimes, the domain in use is not the one that ought to be used for a specific event emitter. Or, the event emitter could have been created in the context of one domain, but ought to instead be bound to some other domain.
For example, there could be one domain in use for an HTTP server, but perhaps we would like to have a separate domain to use for each request.
That is possible via explicit binding.
For example:
// create a top-level domain for the server
var serverDomain = domain.create();
serverDomain.run(function() {
// server is created in the scope of serverDomain
http.createServer(function(req, res) {
// req and res are also created in the scope of serverDomain
// however, we'd prefer to have a separate domain for each request.
// create it first thing, and add req and res to it.
var reqd = domain.create();
reqd.add(req);
reqd.add(res);
reqd.on('error', function(er) {
console.error('Error', er, req.url);
try {
res.writeHead(500);
res.end('Error occurred, sorry.');
} catch (er) {
console.error('Error sending 500', er, req.url);
}
});
}).listen(1337);
});
domain.create()#
- return: Domain
Returns a new Domain object.
Class: Domain#
The Domain class encapsulates the functionality of routing errors and uncaught exceptions to the active Domain object.
Domain is a child class of EventEmitter. To handle the errors that it
catches, listen to its error
event.
domain.run(fn)#
fn
Function
Run the supplied function in the context of the domain, implicitly binding all event emitters, timers, and lowlevel requests that are created in that context.
This is the most basic way to use a domain.
Example:
var d = domain.create();
d.on('error', function(er) {
console.error('Caught error!', er);
});
d.run(function() {
process.nextTick(function() {
setTimeout(function() { // simulating some various async stuff
fs.open('non-existent file', 'r', function(er, fd) {
if (er) throw er;
// proceed...
});
}, 100);
});
});
In this example, the d.on('error')
handler will be triggered, rather
than crashing the program.
domain.members#
- Array
An array of timers and event emitters that have been explicitly added to the domain.
domain.add(emitter)#
emitter
EventEmitter | Timer emitter or timer to be added to the domain
Explicitly adds an emitter to the domain. If any event handlers called by
the emitter throw an error, or if the emitter emits an error
event, it
will be routed to the domain's error
event, just like with implicit
binding.
This also works with timers that are returned from setInterval
and
setTimeout
. If their callback function throws, it will be caught by
the domain 'error' handler.
If the Timer or EventEmitter was already bound to a domain, it is removed from that one, and bound to this one instead.
domain.remove(emitter)#
emitter
EventEmitter | Timer emitter or timer to be removed from the domain
The opposite of domain.add(emitter)
. Removes domain handling from the
specified emitter.
domain.bind(callback)#
callback
Function The callback function- return: Function The bound function
The returned function will be a wrapper around the supplied callback
function. When the returned function is called, any errors that are
thrown will be routed to the domain's error
event.
Example#
var d = domain.create();
function readSomeFile(filename, cb) {
fs.readFile(filename, 'utf8', d.bind(function(er, data) {
// if this throws, it will also be passed to the domain
return cb(er, data ? JSON.parse(data) : null);
}));
}
d.on('error', function(er) {
// an error occurred somewhere.
// if we throw it now, it will crash the program
// with the normal line number and stack message.
});
domain.intercept(callback)#
callback
Function The callback function- return: Function The intercepted function
This method is almost identical to domain.bind(callback)
. However, in
addition to catching thrown errors, it will also intercept Error
objects sent as the first argument to the function.
In this way, the common if (er) return callback(er);
pattern can be replaced
with a single error handler in a single place.
Example#
var d = domain.create();
function readSomeFile(filename, cb) {
fs.readFile(filename, 'utf8', d.intercept(function(data) {
// note, the first argument is never passed to the
// callback since it is assumed to be the 'Error' argument
// and thus intercepted by the domain.
// if this throws, it will also be passed to the domain
// so the error-handling logic can be moved to the 'error'
// event on the domain instead of being repeated throughout
// the program.
return cb(null, JSON.parse(data));
}));
}
d.on('error', function(er) {
// an error occurred somewhere.
// if we throw it now, it will crash the program
// with the normal line number and stack message.
});
domain.enter()#
The enter
method is plumbing used by the run
, bind
, and intercept
methods to set the active domain. It sets domain.active
and process.domain
to the domain, and implicitly pushes the domain onto the domain stack managed
by the domain module (see domain.exit()
for details on the domain stack). The
call to enter
delimits the beginning of a chain of asynchronous calls and I/O
operations bound to a domain.
Calling enter
changes only the active domain, and does not alter the domain
itself. Enter
and exit
can be called an arbitrary number of times on a
single domain.
If the domain on which enter
is called has been disposed, enter
will return
without setting the domain.
domain.exit()#
The exit
method exits the current domain, popping it off the domain stack.
Any time execution is going to switch to the context of a different chain of
asynchronous calls, it's important to ensure that the current domain is exited.
The call to exit
delimits either the end of or an interruption to the chain
of asynchronous calls and I/O operations bound to a domain.
If there are multiple, nested domains bound to the current execution context,
exit
will exit any domains nested within this domain.
Calling exit
changes only the active domain, and does not alter the domain
itself. Enter
and exit
can be called an arbitrary number of times on a
single domain.
If the domain on which exit
is called has been disposed, exit
will return
without exiting the domain.
domain.dispose()#
The dispose method destroys a domain, and makes a best effort attempt to clean up any and all IO that is associated with the domain. Streams are aborted, ended, closed, and/or destroyed. Timers are cleared. Explicitly bound callbacks are no longer called. Any error events that are raised as a result of this are ignored.
The intention of calling dispose
is generally to prevent cascading
errors when a critical part of the Domain context is found to be in an
error state.
Once the domain is disposed the dispose
event will emit.
Note that IO might still be performed. However, to the highest degree possible, once a domain is disposed, further errors from the emitters in that set will be ignored. So, even if some remaining actions are still in flight, Node.js will not communicate further about them.
Buffer#
Stability: 3 - Stable
Pure JavaScript is Unicode friendly but not nice to binary data. When dealing with TCP streams or the file system, it's necessary to handle octet streams. Node has several strategies for manipulating, creating, and consuming octet streams.
Raw data is stored in instances of the Buffer
class. A Buffer
is similar
to an array of integers but corresponds to a raw memory allocation outside
the V8 heap. A Buffer
cannot be resized.
The Buffer
class is a global, making it very rare that one would need
to ever require('buffer')
.
Converting between Buffers and JavaScript string objects requires an explicit encoding method. Here are the different string encodings.
'ascii'
- for 7 bit ASCII data only. This encoding method is very fast, and will strip the high bit if set.Note that when converting from string to buffer, this encoding converts a null character (
'\0'
or'\u0000'
) into0x20
(character code of a space). If you want to convert a null character into0x00
, you should use'utf8'
.'utf8'
- Multibyte encoded Unicode characters. Many web pages and other document formats use UTF-8.'utf16le'
- 2 or 4 bytes, little endian encoded Unicode characters. Surrogate pairs (U+10000 to U+10FFFF) are supported.'ucs2'
- Alias of'utf16le'
.'base64'
- Base64 string encoding.'binary'
- A way of encoding raw binary data into strings by using only the first 8 bits of each character. This encoding method is deprecated and should be avoided in favor ofBuffer
objects where possible. This encoding will be removed in future versions of Node.'hex'
- Encode each byte as two hexadecimal characters.
Creating a typed array from a Buffer
works with the following caveats:
The buffer's memory is copied, not shared.
The buffer's memory is interpreted as an array, not a byte array. That is,
new Uint32Array(new Buffer([1,2,3,4]))
creates a 4-elementUint32Array
with elements[1,2,3,4]
, not anUint32Array
with a single element[0x1020304]
or[0x4030201]
.
NOTE: Node.js v0.8 simply retained a reference to the buffer in array.buffer
instead of cloning it.
While more efficient, it introduces subtle incompatibilities with the typed
arrays specification. ArrayBuffer#slice()
makes a copy of the slice while
Buffer#slice()
creates a view.
Class: Buffer#
The Buffer class is a global type for dealing with binary data directly. It can be constructed in a variety of ways.
new Buffer(size)#
size
Number
Allocates a new buffer of size
octets.
new Buffer(array)#
array
Array
Allocates a new buffer using an array
of octets.
new Buffer(str, [encoding])#
str
String - string to encode.encoding
String - encoding to use, Optional.
Allocates a new buffer containing the given str
.
encoding
defaults to 'utf8'
.
Class Method: Buffer.isEncoding(encoding)#
encoding
String The encoding string to test
Returns true if the encoding
is a valid encoding argument, or false
otherwise.
buf.write(string, [offset], [length], [encoding])#
string
String - data to be written to bufferoffset
Number, Optional, Default: 0length
Number, Optional, Default:buffer.length - offset
encoding
String, Optional, Default: 'utf8'
Writes string
to the buffer at offset
using the given encoding.
offset
defaults to 0
, encoding
defaults to 'utf8'
. length
is
the number of bytes to write. Returns number of octets written. If buffer
did
not contain enough space to fit the entire string, it will write a partial
amount of the string. length
defaults to buffer.length - offset
.
The method will not write partial characters.
buf = new Buffer(256);
len = buf.write('\u00bd + \u00bc = \u00be', 0);
console.log(len + " bytes: " + buf.toString('utf8', 0, len));
The number of characters written (which may be different than the number of
bytes written) is set in Buffer._charsWritten
and will be overwritten the
next time buf.write()
is called.
buf.toString([encoding], [start], [end])#
encoding
String, Optional, Default: 'utf8'start
Number, Optional, Default: 0end
Number, Optional, Default:buffer.length
Decodes and returns a string from buffer data encoded using the specified
character set encoding. If encoding
is undefined
or null
, then encoding
defaults to 'utf8'. The
start and
end parameters default to
0 and
buffer.length when
undefined`.
buf = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf[i] = i + 97; // 97 is ASCII a
}
buf.toString('ascii'); // outputs: abcdefghijklmnopqrstuvwxyz
buf.toString('ascii',0,5); // outputs: abcde
buf.toString('utf8',0,5); // outputs: abcde
buf.toString(undefined,0,5); // encoding defaults to 'utf8', outputs abcde
See buffer.write()
example, above.
buf.toJSON()#
Returns a JSON-representation of the Buffer instance, which is identical to the
output for JSON Arrays. JSON.stringify
implicitly calls this function when
stringifying a Buffer instance.
Example:
var buf = new Buffer('test');
var json = JSON.stringify(buf);
console.log(json);
// '[116,101,115,116]'
var copy = new Buffer(JSON.parse(json));
console.log(copy);
// <Buffer 74 65 73 74>
buf[index]#
Get and set the octet at index
. The values refer to individual bytes,
so the legal range is between 0x00
and 0xFF
hex or 0
and 255
.
Example: copy an ASCII string into a buffer, one byte at a time:
str = "node.js";
buf = new Buffer(str.length);
for (var i = 0; i < str.length ; i++) {
buf[i] = str.charCodeAt(i);
}
console.log(buf);
// node.js
Class Method: Buffer.isBuffer(obj)#
obj
Object- Return: Boolean
Tests if obj
is a Buffer
.
Class Method: Buffer.byteLength(string, [encoding])#
string
Stringencoding
String, Optional, Default: 'utf8'- Return: Number
Gives the actual byte length of a string. encoding
defaults to 'utf8'
.
This is not the same as String.prototype.length
since that returns the
number of characters in a string.
Example:
str = '\u00bd + \u00bc = \u00be';
console.log(str + ": " + str.length + " characters, " +
Buffer.byteLength(str, 'utf8') + " bytes");
// ½ + ¼ = ¾: 9 characters, 12 bytes
Class Method: Buffer.concat(list, [totalLength])#
list
Array List of Buffer objects to concattotalLength
Number Total length of the buffers when concatenated
Returns a buffer which is the result of concatenating all the buffers in the list together.
If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.
If the list has exactly one item, then the first item of the list is returned.
If the list has more than one item, then a new Buffer is created.
If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.
buf.length#
- Number
The size of the buffer in bytes. Note that this is not necessarily the size
of the contents. length
refers to the amount of memory allocated for the
buffer object. It does not change when the contents of the buffer are changed.
buf = new Buffer(1234);
console.log(buf.length);
buf.write("some string", 0, "ascii");
console.log(buf.length);
// 1234
// 1234
While the length
property is not immutable, changing the value of length
can result in undefined and inconsistent behavior. Applications that wish to
modify the length of a buffer should therefore treat length
as read-only and
use buf.slice
to create a new buffer.
buf = new Buffer(10);
buf.write("abcdefghj", 0, "ascii");
console.log(buf.length); // 10
buf = buf.slice(0,5);
console.log(buf.length); // 5
buf.copy(targetBuffer, [targetStart], [sourceStart], [sourceEnd])#
targetBuffer
Buffer object - Buffer to copy intotargetStart
Number, Optional, Default: 0sourceStart
Number, Optional, Default: 0sourceEnd
Number, Optional, Default:buffer.length
Copies data from a region of this buffer to a region in the target buffer even
if the target memory region overlaps with the source. If undefined
the
targetStart
and sourceStart
parameters default to 0
while sourceEnd
defaults to buffer.length
.
Example: build two Buffers, then copy buf1
from byte 16 through byte 19
into buf2
, starting at the 8th byte in buf2
.
buf1 = new Buffer(26);
buf2 = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf1[i] = i + 97; // 97 is ASCII a
buf2[i] = 33; // ASCII !
}
buf1.copy(buf2, 8, 16, 20);
console.log(buf2.toString('ascii', 0, 25));
// !!!!!!!!qrst!!!!!!!!!!!!!
Example: Build a single buffer, then copy data from one region to an overlapping region in the same buffer
buf = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf[i] = i + 97; // 97 is ASCII a
}
buf.copy(buf, 0, 4, 10);
console.log(buf.toString());
// efghijghijklmnopqrstuvwxyz
buf.slice([start], [end])#
start
Number, Optional, Default: 0end
Number, Optional, Default:buffer.length
Returns a new buffer which references the same memory as the old, but offset
and cropped by the start
(defaults to 0
) and end
(defaults to
buffer.length
) indexes. Negative indexes start from the end of the buffer.
Modifying the new buffer slice will modify memory in the original buffer!
Example: build a Buffer with the ASCII alphabet, take a slice, then modify one byte from the original Buffer.
var buf1 = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf1[i] = i + 97; // 97 is ASCII a
}
var buf2 = buf1.slice(0, 3);
console.log(buf2.toString('ascii', 0, buf2.length));
buf1[0] = 33;
console.log(buf2.toString('ascii', 0, buf2.length));
// abc
// !bc
buf.readUInt8(offset, [noAssert])#
offset
NumbernoAssert
Boolean, Optional, Default: false- Return: Number
Reads an unsigned 8 bit integer from the buffer at the specified offset.
Set noAssert
to true to skip validation of offset
. This means that offset
may be beyond the end of the buffer. Defaults to false
.
Example:
var buf = new Buffer(4);
buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;
for (ii = 0; ii < buf.length; ii++) {
console.log(buf.readUInt8(ii));
}
// 0x3
// 0x4
// 0x23
// 0x42
buf.readUInt16LE(offset, [noAssert])#
buf.readUInt16BE(offset, [noAssert])#
offset
NumbernoAssert
Boolean, Optional, Default: false- Return: Number
Reads an unsigned 16 bit integer from the buffer at the specified offset with specified endian format.
Set noAssert
to true to skip validation of offset
. This means that offset
may be beyond the end of the buffer. Defaults to false
.
Example:
var buf = new Buffer(4);
buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;
console.log(buf.readUInt16BE(0));
console.log(buf.readUInt16LE(0));
console.log(buf.readUInt16BE(1));
console.log(buf.readUInt16LE(1));
console.log(buf.readUInt16BE(2));
console.log(buf.readUInt16LE(2));
// 0x0304
// 0x0403
// 0x0423
// 0x2304
// 0x2342
// 0x4223
buf.readUInt32LE(offset, [noAssert])#
buf.readUInt32BE(offset, [noAssert])#
offset
NumbernoAssert
Boolean, Optional, Default: false- Return: Number
Reads an unsigned 32 bit integer from the buffer at the specified offset with specified endian format.
Set noAssert
to true to skip validation of offset
. This means that offset
may be beyond the end of the buffer. Defaults to false
.
Example:
var buf = new Buffer(4);
buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;
console.log(buf.readUInt32BE(0));
console.log(buf.readUInt32LE(0));
// 0x03042342
// 0x42230403
buf.readInt8(offset, [noAssert])#
offset
NumbernoAssert
Boolean, Optional, Default: false- Return: Number
Reads a signed 8 bit integer from the buffer at the specified offset.
Set noAssert
to true to skip validation of offset
. This means that offset
may be beyond the end of the buffer. Defaults to false
.
Works as buffer.readUInt8
, except buffer contents are treated as two's
complement signed values.
buf.readInt16LE(offset, [noAssert])#
buf.readInt16BE(offset, [noAssert])#
offset
NumbernoAssert
Boolean, Optional, Default: false- Return: Number
Reads a signed 16 bit integer from the buffer at the specified offset with specified endian format.
Set noAssert
to true to skip validation of offset
. This means that offset
may be beyond the end of the buffer. Defaults to false
.
Works as buffer.readUInt16*
, except buffer contents are treated as two's
complement signed values.
buf.readInt32LE(offset, [noAssert])#
buf.readInt32BE(offset, [noAssert])#
offset
NumbernoAssert
Boolean, Optional, Default: false- Return: Number
Reads a signed 32 bit integer from the buffer at the specified offset with specified endian format.
Set noAssert
to true to skip validation of offset
. This means that offset
may be beyond the end of the buffer. Defaults to false
.
Works as buffer.readUInt32*
, except buffer contents are treated as two's
complement signed values.
buf.readFloatLE(offset, [noAssert])#
buf.readFloatBE(offset, [noAssert])#
offset
NumbernoAssert
Boolean, Optional, Default: false- Return: Number
Reads a 32 bit float from the buffer at the specified offset with specified endian format.
Set noAssert
to true to skip validation of offset
. This means that offset
may be beyond the end of the buffer. Defaults to false
.
Example:
var buf = new Buffer(4);
buf[0] = 0x00;
buf[1] = 0x00;
buf[2] = 0x80;
buf[3] = 0x3f;
console.log(buf.readFloatLE(0));
// 0x01
buf.readDoubleLE(offset, [noAssert])#
buf.readDoubleBE(offset, [noAssert])#
offset
NumbernoAssert
Boolean, Optional, Default: false- Return: Number
Reads a 64 bit double from the buffer at the specified offset with specified endian format.
Set noAssert
to true to skip validation of offset
. This means that offset
may be beyond the end of the buffer. Defaults to false
.
Example:
var buf = new Buffer(8);
buf[0] = 0x55;
buf[1] = 0x55;
buf[2] = 0x55;
buf[3] = 0x55;
buf[4] = 0x55;
buf[5] = 0x55;
buf[6] = 0xd5;
buf[7] = 0x3f;
console.log(buf.readDoubleLE(0));
// 0.3333333333333333
buf.writeUInt8(value, offset, [noAssert])#
value
Numberoffset
NumbernoAssert
Boolean, Optional, Default: false
Writes value
to the buffer at the specified offset. Note, value
must be a
valid unsigned 8 bit integer.
Set noAssert
to true to skip validation of value
and offset
. This means
that value
may be too large for the specific function and offset
may be
beyond the end of the buffer leading to the values being silently dropped. This
should not be used unless you are certain of correctness. Defaults to false
.
Example:
var buf = new Buffer(4);
buf.writeUInt8(0x3, 0);
buf.writeUInt8(0x4, 1);
buf.writeUInt8(0x23, 2);
buf.writeUInt8(0x42, 3);
console.log(buf);
// <Buffer 03 04 23 42>
buf.writeUInt16LE(value, offset, [noAssert])#
buf.writeUInt16BE(value, offset, [noAssert])#
value
Numberoffset
NumbernoAssert
Boolean, Optional, Default: false
Writes value
to the buffer at the specified offset with specified endian
format. Note, value
must be a valid unsigned 16 bit integer.
Set noAssert
to true to skip validation of value
and offset
. This means
that value
may be too large for the specific function and offset
may be
beyond the end of the buffer leading to the values being silently dropped. This
should not be used unless you are certain of correctness. Defaults to false
.
Example:
var buf = new Buffer(4);
buf.writeUInt16BE(0xdead, 0);
buf.writeUInt16BE(0xbeef, 2);
console.log(buf);
buf.writeUInt16LE(0xdead, 0);
buf.writeUInt16LE(0xbeef, 2);
console.log(buf);
// <Buffer de ad be ef>
// <Buffer ad de ef be>
buf.writeUInt32LE(value, offset, [noAssert])#
buf.writeUInt32BE(value, offset, [noAssert])#
value
Numberoffset
NumbernoAssert
Boolean, Optional, Default: false
Writes value
to the buffer at the specified offset with specified endian
format. Note, value
must be a valid unsigned 32 bit integer.
Set noAssert
to true to skip validation of value
and offset
. This means
that value
may be too large for the specific function and offset
may be
beyond the end of the buffer leading to the values being silently dropped. This
should not be used unless you are certain of correctness. Defaults to false
.
Example:
var buf = new Buffer(4);
buf.writeUInt32BE(0xfeedface, 0);
console.log(buf);
buf.writeUInt32LE(0xfeedface, 0);
console.log(buf);
// <Buffer fe ed fa ce>
// <Buffer ce fa ed fe>
buf.writeInt8(value, offset, [noAssert])#
value
Numberoffset
NumbernoAssert
Boolean, Optional, Default: false
Writes value
to the buffer at the specified offset. Note, value
must be a
valid signed 8 bit integer.
Set noAssert
to true to skip validation of value
and offset
. This means
that value
may be too large for the specific function and offset
may be
beyond the end of the buffer leading to the values being silently dropped. This
should not be used unless you are certain of correctness. Defaults to false
.
Works as buffer.writeUInt8
, except value is written out as a two's complement
signed integer into buffer
.
buf.writeInt16LE(value, offset, [noAssert])#
buf.writeInt16BE(value, offset, [noAssert])#
value
Numberoffset
NumbernoAssert
Boolean, Optional, Default: false
Writes value
to the buffer at the specified offset with specified endian
format. Note, value
must be a valid signed 16 bit integer.
Set noAssert
to true to skip validation of value
and offset
. This means
that value
may be too large for the specific function and offset
may be
beyond the end of the buffer leading to the values being silently dropped. This
should not be used unless you are certain of correctness. Defaults to false
.
Works as buffer.writeUInt16*
, except value is written out as a two's
complement signed integer into buffer
.
buf.writeInt32LE(value, offset, [noAssert])#
buf.writeInt32BE(value, offset, [noAssert])#
value
Numberoffset
NumbernoAssert
Boolean, Optional, Default: false
Writes value
to the buffer at the specified offset with specified endian
format. Note, value
must be a valid signed 32 bit integer.
Set noAssert
to true to skip validation of value
and offset
. This means
that value
may be too large for the specific function and offset
may be
beyond the end of the buffer leading to the values being silently dropped. This
should not be used unless you are certain of correctness. Defaults to false
.
Works as buffer.writeUInt32*
, except value is written out as a two's
complement signed integer into buffer
.
buf.writeFloatLE(value, offset, [noAssert])#
buf.writeFloatBE(value, offset, [noAssert])#
value
Numberoffset
NumbernoAssert
Boolean, Optional, Default: false
Writes value
to the buffer at the specified offset with specified endian
format. Note, behavior is unspecified if value
is not a 32 bit float.
Set noAssert
to true to skip validation of value
and offset
. This means
that value
may be too large for the specific function and offset
may be
beyond the end of the buffer leading to the values being silently dropped. This
should not be used unless you are certain of correctness. Defaults to false
.
Example:
var buf = new Buffer(4);
buf.writeFloatBE(0xcafebabe, 0);
console.log(buf);
buf.writeFloatLE(0xcafebabe, 0);
console.log(buf);
// <Buffer 4f 4a fe bb>
// <Buffer bb fe 4a 4f>
buf.writeDoubleLE(value, offset, [noAssert])#
buf.writeDoubleBE(value, offset, [noAssert])#
value
Numberoffset
NumbernoAssert
Boolean, Optional, Default: false
Writes value
to the buffer at the specified offset with specified endian
format. Note, value
must be a valid 64 bit double.
Set noAssert
to true to skip validation of value
and offset
. This means
that value
may be too large for the specific function and offset
may be
beyond the end of the buffer leading to the values being silently dropped. This
should not be used unless you are certain of correctness. Defaults to false
.
Example:
var buf = new Buffer(8);
buf.writeDoubleBE(0xdeadbeefcafebabe, 0);
console.log(buf);
buf.writeDoubleLE(0xdeadbeefcafebabe, 0);
console.log(buf);
// <Buffer 43 eb d5 b7 dd f9 5f d7>
// <Buffer d7 5f f9 dd b7 d5 eb 43>
buf.fill(value, [offset], [end])#
value
offset
Number, Optionalend
Number, Optional
Fills the buffer with the specified value. If the offset
(defaults to 0
)
and end
(defaults to buffer.length
) are not given it will fill the entire
buffer.
var b = new Buffer(50);
b.fill("h");
buffer.INSPECT_MAX_BYTES#
- Number, Default: 50
How many bytes will be returned when buffer.inspect()
is called. This can
be overridden by user modules.
Note that this is a property on the buffer module returned by
require('buffer')
, not on the Buffer global, or a buffer instance.
Class: SlowBuffer#
This class is primarily for internal use. JavaScript programs should use Buffer instead of using SlowBuffer.
In order to avoid the overhead of allocating many C++ Buffer objects for small blocks of memory in the lifetime of a server, Node allocates memory in 8Kb (8192 byte) chunks. If a buffer is smaller than this size, then it will be backed by a parent SlowBuffer object. If it is larger than this, then Node will allocate a SlowBuffer slab for it directly.
Stream#
Stability: 2 - Unstable
A stream is an abstract interface implemented by various objects in Node. For example a request to an HTTP server is a stream, as is stdout. Streams are readable, writable, or both. All streams are instances of EventEmitter
You can load the Stream base classes by doing require('stream')
.
There are base classes provided for Readable streams, Writable
streams, Duplex streams, and Transform streams.
This document is split up into 3 sections. The first explains the parts of the API that you need to be aware of to use streams in your programs. If you never implement a streaming API yourself, you can stop there.
The second section explains the parts of the API that you need to use if you implement your own custom streams yourself. The API is designed to make this easy for you to do.
The third section goes into more depth about how streams work, including some of the internal mechanisms and functions that you should probably not modify unless you definitely know what you are doing.
API for Stream Consumers#
Streams can be either Readable, Writable, or both (Duplex).
All streams are EventEmitters, but they also have other custom methods and properties depending on whether they are Readable, Writable, or Duplex.
If a stream is both Readable and Writable, then it implements all of the methods and events below. So, a Duplex or Transform stream is fully described by this API, though their implementation may be somewhat different.
It is not necessary to implement Stream interfaces in order to consume streams in your programs. If you are implementing streaming interfaces in your own program, please also refer to API for Stream Implementors below.
Almost all Node programs, no matter how simple, use Streams in some way. Here is an example of using Streams in a Node program:
var http = require('http');
var server = http.createServer(function (req, res) {
// req is an http.IncomingMessage, which is a Readable Stream
// res is an http.ServerResponse, which is a Writable Stream
var body = '';
// we want to get the data as utf8 strings
// If you don't set an encoding, then you'll get Buffer objects
req.setEncoding('utf8');
// Readable streams emit 'data' events once a listener is added
req.on('data', function (chunk) {
body += chunk;
})
// the end event tells you that you have entire body
req.on('end', function () {
try {
var data = JSON.parse(body);
} catch (er) {
// uh oh! bad json!
res.statusCode = 400;
return res.end('error: ' + er.message);
}
// write back something interesting to the user:
res.write(typeof data);
res.end();
})
})
server.listen(1337);
// $ curl localhost:1337 -d '{}'
// object
// $ curl localhost:1337 -d '"foo"'
// string
// $ curl localhost:1337 -d 'not json'
// error: Unexpected token o
Class: stream.Readable#
The Readable stream interface is the abstraction for a source of data that you are reading from. In other words, data comes out of a Readable stream.
A Readable stream will not start emitting data until you indicate that you are ready to receive it.
Readable streams have two "modes": a flowing mode and a non-flowing
mode. When in flowing mode, data is read from the underlying system
and provided to your program as fast as possible. In non-flowing
mode, you must explicitly call stream.read()
to get chunks of data
out.
Examples of readable streams include:
- http responses, on the client
- http requests, on the server
- fs read streams
- zlib streams
- crypto streams
- tcp sockets
- child process stdout and stderr
- process.stdin
Event: 'readable'#
When a chunk of data can be read from the stream, it will emit a
'readable'
event.
In some cases, listening for a 'readable'
event will cause some data
to be read into the internal buffer from the underlying system, if it
hadn't already.
var readable = getReadableStreamSomehow();
readable.on('readable', function() {
// there is some data to read now
})
Once the internal buffer is drained, a readable
event will fire
again when more data is available.
Event: 'data'#
chunk
Buffer | String The chunk of data.
If you attach a data
event listener, then it will switch the stream
into flowing mode, and data will be passed to your handler as soon as
it is available.
If you just want to get all the data out of the stream as fast as possible, this is the best way to do so.
var readable = getReadableStreamSomehow();
readable.on('data', function(chunk) {
console.log('got %d bytes of data', chunk.length);
})
Event: 'end'#
This event fires when there will be no more data to read.
Note that the end
event will not fire unless the data is
completely consumed. This can be done by switching into flowing mode,
or by calling read()
repeatedly until you get to the end.
var readable = getReadableStreamSomehow();
readable.on('data', function(chunk) {
console.log('got %d bytes of data', chunk.length);
})
readable.on('end', function() {
console.log('there will be no more data.');
});
Event: 'close'#
Emitted when the underlying resource (for example, the backing file descriptor) has been closed. Not all streams will emit this.
Event: 'error'#
- Error Object
Emitted if there was an error receiving data.
readable.read([size])#
size
Number Optional argument to specify how much data to read.- Return String | Buffer | null
The read()
method pulls some data out of the internal buffer and
returns it. If there is no data available, then it will return
null
.
If you pass in a size
argument, then it will return that many
bytes. If size
bytes are not available, then it will return null
.
If you do not specify a size
argument, then it will return all the
data in the internal buffer.
This method should only be called in non-flowing mode. In flowing-mode, this method is called automatically until the internal buffer is drained.
var readable = getReadableStreamSomehow();
readable.on('readable', function() {
var chunk;
while (null !== (chunk = readable.read())) {
console.log('got %d bytes of data', chunk.length);
}
});
readable.setEncoding(encoding)#
encoding
String The encoding to use.
Call this function to cause the stream to return strings of the
specified encoding instead of Buffer objects. For example, if you do
readable.setEncoding('utf8')
, then the output data will be
interpreted as UTF-8 data, and returned as strings. If you do
readable.setEncoding('hex')
, then the data will be encoded in
hexadecimal string format.
This properly handles multi-byte characters that would otherwise be
potentially mangled if you simply pulled the Buffers directly and
called buf.toString(encoding)
on them. If you want to read the data
as strings, always use this method.
var readable = getReadableStreamSomehow();
readable.setEncoding('utf8');
readable.on('data', function(chunk) {
assert.equal(typeof chunk, 'string');
console.log('got %d characters of string data', chunk.length);
})
readable.resume()#
This method will cause the readable stream to resume emitting data
events.
This method will switch the stream into flowing-mode. If you do not
want to consume the data from a stream, but you do want to get to
its end
event, you can call readable.resume()
to open the flow of
data.
var readable = getReadableStreamSomehow();
readable.resume();
readable.on('end', function(chunk) {
console.log('got to the end, but did not read anything');
})
readable.pause()#
This method will cause a stream in flowing-mode to stop emitting
data
events. Any data that becomes available will remain in the
internal buffer.
This method is only relevant in flowing mode. When called on a non-flowing stream, it will switch into flowing mode, but remain paused.
var readable = getReadableStreamSomehow();
readable.on('data', function(chunk) {
console.log('got %d bytes of data', chunk.length);
readable.pause();
console.log('there will be no more data for 1 second');
setTimeout(function() {
console.log('now data will start flowing again');
readable.resume();
}, 1000);
})
readable.pipe(destination, [options])#
destination
Writable Stream The destination for writing dataoptions
Object Pipe optionsend
Boolean End the writer when the reader ends. Default =true
This method pulls all the data out of a readable stream, and writes it to the supplied destination, automatically managing the flow so that the destination is not overwhelmed by a fast readable stream.
Multiple destinations can be piped to safely.
var readable = getReadableStreamSomehow();
var writable = fs.createWriteStream('file.txt');
// All the data from readable goes into 'file.txt'
readable.pipe(writable);
This function returns the destination stream, so you can set up pipe chains like so:
var r = fs.createReadStream('file.txt');
var z = zlib.createGzip();
var w = fs.createWriteStream('file.txt.gz');
r.pipe(z).pipe(w);
For example, emulating the Unix cat
command:
process.stdin.pipe(process.stdout);
By default end()
is called on the destination when the source stream
emits end
, so that destination
is no longer writable. Pass { end:
false }
as options
to keep the destination stream open.
This keeps writer
open so that "Goodbye" can be written at the
end.
reader.pipe(writer, { end: false });
reader.on('end', function() {
writer.end('Goodbye\n');
});
Note that process.stderr
and process.stdout
are never closed until
the process exits, regardless of the specified options.
readable.unpipe([destination])#
destination
Writable Stream Optional specific stream to unpipe
This method will remove the hooks set up for a previous pipe()
call.
If the destination is not specified, then all pipes are removed.
If the destination is specified, but no pipe is set up for it, then this is a no-op.
var readable = getReadableStreamSomehow();
var writable = fs.createWriteStream('file.txt');
// All the data from readable goes into 'file.txt',
// but only for the first second
readable.pipe(writable);
setTimeout(function() {
console.log('stop writing to file.txt');
readable.unpipe(writable);
console.log('manually close the file stream');
writable.end();
}, 1000);
readable.unshift(chunk)#
chunk
Buffer | String Chunk of data to unshift onto the read queue
This is useful in certain cases where a stream is being consumed by a parser, which needs to "un-consume" some data that it has optimistically pulled out of the source, so that the stream can be passed on to some other party.
If you find that you must often call stream.unshift(chunk)
in your
programs, consider implementing a Transform stream instead. (See API
for Stream Implementors, below.)
// Pull off a header delimited by \n\n
// use unshift() if we get too much
// Call the callback with (error, header, stream)
var StringDecoder = require('string_decoder').StringDecoder;
function parseHeader(stream, callback) {
stream.on('error', callback);
stream.on('readable', onReadable);
var decoder = new StringDecoder('utf8');
var header = '';
function onReadable() {
var chunk;
while (null !== (chunk = stream.read())) {
var str = decoder.write(chunk);
if (str.match(/\n\n/)) {
// found the header boundary
var split = str.split(/\n\n/);
header += split.shift();
var remaining = split.join('\n\n');
var buf = new Buffer(remaining, 'utf8');
if (buf.length)
stream.unshift(buf);
stream.removeListener('error', callback);
stream.removeListener('readable', onReadable);
// now the body of the message can be read from the stream.
callback(null, header, stream);
} else {
// still reading the header.
header += str;
}
}
}
}
readable.wrap(stream)#
stream
Stream An "old style" readable stream
Versions of Node prior to v0.10 had streams that did not implement the entire Streams API as it is today. (See "Compatibility" below for more information.)
If you are using an older Node library that emits 'data'
events and
has a pause()
method that is advisory only, then you can use the
wrap()
method to create a Readable stream that uses the old stream
as its data source.
You will very rarely ever need to call this function, but it exists as a convenience for interacting with old Node programs and libraries.
For example:
var OldReader = require('./old-api-module.js').OldReader;
var oreader = new OldReader;
var Readable = require('stream').Readable;
var myReader = new Readable().wrap(oreader);
myReader.on('readable', function() {
myReader.read(); // etc.
});
Class: stream.Writable#
The Writable stream interface is an abstraction for a destination that you are writing data to.
Examples of writable streams include:
- http requests, on the client
- http responses, on the server
- fs write streams
- zlib streams
- crypto streams
- tcp sockets
- child process stdin
- process.stdout, process.stderr
writable.write(chunk, [encoding], [callback])#
chunk
String | Buffer The data to writeencoding
String The encoding, ifchunk
is a Stringcallback
Function Callback for when this chunk of data is flushed- Returns: Boolean True if the data was handled completely.
This method writes some data to the underlying system, and calls the supplied callback once the data has been fully handled.
The return value indicates if you should continue writing right now.
If the data had to be buffered internally, then it will return
false
. Otherwise, it will return true
.
This return value is strictly advisory. You MAY continue to write,
even if it returns false
. However, writes will be buffered in
memory, so it is best not to do this excessively. Instead, wait for
the drain
event before writing more data.
Event: 'drain'#
If a writable.write(chunk)
call returns false, then the drain
event will indicate when it is appropriate to begin writing more data
to the stream.
// Write the data to the supplied writable stream 1MM times.
// Be attentive to back-pressure.
function writeOneMillionTimes(writer, data, encoding, callback) {
var i = 1000000;
write();
function write() {
var ok = true;
do {
i -= 1;
if (i === 0) {
// last time!
writer.write(data, encoding, callback);
} else {
// see if we should continue, or wait
// don't pass the callback, because we're not done yet.
ok = writer.write(data, encoding);
}
} while (i > 0 && ok);
if (i > 0) {
// had to stop early!
// write some more once it drains
writer.once('drain', write);
}
}
}
writable.end([chunk], [encoding], [callback])#
chunk
String | Buffer Optional data to writeencoding
String The encoding, ifchunk
is a Stringcallback
Function Optional callback for when the stream is finished
Call this method when no more data will be written to the stream. If
supplied, the callback is attached as a listener on the finish
event.
// write 'hello, ' and then end with 'world!'
var file = fs.createWriteStream('example.txt');
file.write('hello, ');
file.end('world!');
Calling write()
after calling end()
will raise an error:
// end with 'world!' and then write with 'hello, ' will raise an error
var file = fs.createWriteStream('example.txt');
file.end('world!');
file.write('hello, ');
Event: 'finish'#
When the end()
method has been called, and all data has been flushed
to the underlying system, this event is emitted.
var writer = getWritableStreamSomehow();
for (var i = 0; i < 100; i ++) {
writer.write('hello, #' + i + '!\n');
}
writer.end('this is the end\n');
writer.on('finish', function() {
console.error('all writes are now complete.');
});
Event: 'pipe'#
src
Readable Stream source stream that is piping to this writable
This is emitted whenever the pipe()
method is called on a readable
stream, adding this writable to its set of destinations.
var writer = getWritableStreamSomehow();
var reader = getReadableStreamSomehow();
writer.on('pipe', function(src) {
console.error('something is piping into the writer');
assert.equal(src, reader);
});
reader.pipe(writer);
Event: 'unpipe'#
This is emitted whenever the unpipe()
method is called on a
readable stream, removing this writable from its set of destinations.
var writer = getWritableStreamSomehow();
var reader = getReadableStreamSomehow();
writer.on('unpipe', function(src) {
console.error('something has stopped piping into the writer');
assert.equal(src, reader);
});
reader.pipe(writer);
reader.unpipe(writer);
Event: 'error'#
- Error object
Emitted if there was an error when writing or piping data.
Class: stream.Duplex#
Duplex streams are streams that implement both the Readable and Writable interfaces. See above for usage.
Examples of Duplex streams include:
Class: stream.Transform#
Transform streams are Duplex streams where the output is in some way computed from the input. They implement both the Readable and Writable interfaces. See above for usage.
Examples of Transform streams include:
API for Stream Implementors#
To implement any sort of stream, the pattern is the same:
- Extend the appropriate parent class in your own subclass. (The
util.inherits
method is particularly helpful for this.) - Call the appropriate parent class constructor in your constructor, to be sure that the internal mechanisms are set up properly.
- Implement one or more specific methods, as detailed below.
The class to extend and the method(s) to implement depend on the sort of stream class you are writing:
Use-case |
Class |
Method(s) to implement |
---|---|---|
Reading only |
||
Writing only |
||
Reading and writing |
||
Operate on written data, then read the result |