Node.js v0.10.18 手冊 & 文檔
目錄
- 關於本文檔
- 概述
- 全局對象
- 控制檯
- 定時器
- Modules
- Addons插件
- process
- Exit Codes
- 事件: 'exit'
- 事件: '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.exitCode
- 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.umask([mask])
- process.uptime()
- process.hrtime()
- utils
- Buffer
- 類: Buffer
- new Buffer(size)
- new Buffer(array)
- new Buffer(str, [encoding])
- 類方法: Buffer.isEncoding(encoding)
- 類方法: Buffer.isBuffer(obj)
- 類方法: Buffer.byteLength(string, [encoding])
- 類方法: Buffer.concat(list, [totalLength])
- buf.length
- buf.write(string, [offset], [length], [encoding])
- buf.toString([encoding], [start], [end])
- buf.toJSON()
- buf[index]
- 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
- 類: SlowBuffer
- 類: Buffer
- 流
- 加密(Crypto)
- crypto.getCiphers()
- crypto.getHashes()
- crypto.createCredentials(details)
- crypto.createHash(algorithm)
- 類: 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)
- Client-initiated renegotiation attack mitigation
- NPN 和 SNI
- tls.getCiphers()
- tls.createServer(options, [secureConnectionListener])
- tls.connect(options, [callback])
- tls.connect(port, [host], [options], [callback])
- 類: tls.TLSSocket
- new tls.TLSSocket(socket, options)
- tls.createSecurePair([credentials], [isServer], [requestCert], [rejectUnauthorized])
- 類: SecurePair
- 類: tls.Server
- 類: CryptoStream
- 類: tls.TLSSocket
- 字符串解碼器
- 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.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.write(fd, data[, position[, encoding]], callback)
- fs.writeSync(fd, buffer, offset, length[, position])
- fs.writeSync(fd, data[, position[, encoding]])
- 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])
- 類: 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)
- 事件: 'listening'
- 事件: 'connection'
- 事件: 'close'
- 事件: 'error'
- 類: 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
- 事件: 'lookup'
- 事件: 'connect'
- 事件: 'data'
- 事件: 'end'
- 事件: 'timeout'
- 事件: 'drain'
- 事件: 'error'
- 事件: 'close'
- net.isIP(input)
- net.isIPv4(input)
- net.isIPv6(input)
- UDP / 數據報套接字
- dgram.createSocket(type, [callback])
- 類: dgram.Socket
- 事件: 'message'
- 事件: 'listening'
- 事件: 'close'
- 事件: '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)
- dns.getServers()
- dns.setServers(servers)
- 錯誤代碼
- HTTP
- http.STATUS_CODES
- http.createServer([requestListener])
- http.createClient([port], [host])
- Class: http.Server
- 事件 : 'request'
- 事件: 'connection'
- 事件: 'close'
- Event: 'checkContinue'
- 事件: '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
- 事件: 'close'
- 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
- 執行 JavaScript
- 子進程
- 斷言 (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
- 例子
- zlib.createGzip([options])
- zlib.createGunzip([options])
- zlib.createDeflate([options])
- zlib.createInflate([options])
- zlib.createDeflateRaw([options])
- zlib.createInflateRaw([options])
- zlib.createUnzip([options])
- 類: zlib.Zlib
- 類: zlib.Gzip
- 類: zlib.Gunzip
- 類: zlib.Deflate
- 類: zlib.Inflate
- 類: zlib.DeflateRaw
- 類: zlib.InflateRaw
- 類: zlib.Unzip
- 快捷方法
- zlib.deflate(buf, [options], callback)
- zlib.deflateRaw(buf, [options], callback)
- zlib.Gzip(buf, [options], callback)
- zlib.gunzip(buf, [options], callback)
- zlib.inflate(buf, [options], callback)
- zlib.inflateRaw(buf, [options], callback)
- zlib.unzip(buf, [options], callback)
- 選項
- 內存使用調優
- 常量
- 操做系統
- 調試器
- 集羣
- Smalloc
關於本文檔#
本文檔的目標是從參考和概念的角度全面解釋 Node.js 的 API,每章節描述一個內置模塊或高級概念。html
在某些狀況下,屬性類型、方法參數以及事件處理過程(handler)參數 會被列在主標題下的列表中。java
每個 .html
文件都對應一分內容相同的結構化 .json
文檔。這個特性如今仍是實驗性質的,但願可以爲一些須要對文檔進行操做的IDE或者其餘工具提供幫助。node
每一個 .html
和 .json
文件都是基於源碼的 doc/api/
目錄下的 .markdown
文件生成的。本文檔使用 tools/doc/generate.js
這個程序來生產的。 HTML 模板文件爲 doc/template.html
。linux
穩定度#
在文檔中,您能夠了解每個小節的穩定性。Node.js的API會有一些小的改變,當它成熟的時候,會有些部分相比另一些來講更加可靠。有一部分接受過嚴格驗證,被大量依賴的API幾乎是不會改變的。也有一些是新增的、實驗性的或者因被證明具備危險性而在從新設計中。c++
穩定度定義以下git
穩定度: 5 - 已鎖定 除非發現嚴重缺陷,該代碼不會被更改。請不要對此區域提出更改,更改提議將被拒絕。
JSON 輸出#
穩定度: 1 - 實驗性
每一個經過 markdown 生成的 HTML 文件都對應於一個具備相同數據的 JSON 文件。程序員
該特性引入於 node v0.6.12。當前是測試性功能。github
概述#
一個輸出 「Hello World」 的簡單 Web 服務器例子:web
console.log('服務器已運行,請打開 http://127.0.0.1:8124/');
要運行這個服務器,先將程序保存爲文件 「example.js」,並使用 node 命令來執行:
> node example.js 服務器已運行,請打開 http://127.0.0.1:8124/
全部的文檔中的例子均使用相同的方式運行。
全局對象#
這些對象在全部模塊中都是可用的。有些對象實際上並不是在全局做用域內而是在模塊做用域內——這種狀況在如下文檔中會特別指出。
global#
- {Object} 全局命名空間對象。
在瀏覽器中,頂級做用域就是全局做用域。這就是說,在瀏覽器中,若是當前是在全局做用域內,var something
將會聲明一個全局變量。在Node中則不一樣。頂級做用域並不是全局做用域,在Node模塊裏的var something
只屬於那個模塊。
process#
- {Object}
進程對象。見 進程對象章節。
console#
- {Object}
用於打印標準輸出和標準錯誤。見控制檯章節。
類: Buffer#
- {Function}
用於處理二進制數據。見Buffer章節。
require()#
- {Function}
引入模塊。見Modules章節。require
實際上並不是全局的而是各個模塊本地的。
require.resolve()#
使用內部的require()
機制查找模塊的位置,但不加載模塊,只返回解析過的模塊文件路徑。
require.cache#
- {Object}
模塊在引入時會緩存到該對象。經過刪除該對象的鍵值,下次調用require
時會從新加載相應模塊。
require.extensions#
穩定度:0 - 已廢棄
- {Object}
指導require
方法如何處理特定的文件擴展名。
將.sjs
文件做爲.js
文件處理:
require.extensions['.sjs'] = require.extensions['.js'];
已廢棄 以前,該列表用於按需編譯非JavaScript模塊並加載進Node。然而,實踐中有更好的方式實現該功能,如經過其餘Node程序加載模塊,或提早將他們編譯成JavaScript代碼。
因爲模塊系統的API已鎖定,該功能可能永遠不會去掉。改動它可能會產生細微的錯誤和複雜性,因此最好保持不變。
__filename#
- {String}
當前所執行代碼文件的文件路徑。這是該代碼文件通過解析後的絕對路徑。對於主程序來講,這和命令行中使用的文件路徑未必是相同的。在模塊中此變量值是該模塊文件的路徑。
例子:在/Users/mjr
下運行node example.js
console.log(__filename); // /Users/mjr/example.js
__filename
實際上並不是全局的而是各個模塊本地的。
__dirname#
- {String}
當前執行腳本所在目錄的目錄名。
例子:在/Users/mjr
下運行node example.js
console.log(__dirname); // /Users/mjr
__dirname
實際上並不是全局的而是各個模塊本地的。
module#
- {Object}
當前模塊的引用。特別地,module.exports
和exports
指向同一個對象。module
實際上並不是全局的而是各個模塊本地的。
詳情可見模塊系統文檔。
exports#
module.exports
對象的引用,該對象被當前模塊的全部實例所共享,經過require()
可訪問該對象。 什麼時候使用exports
以及什麼時候使用module.exports
的詳情可參見模塊系統文檔。 exports
實際上並不是全局的而是各個模塊本地的。
詳情可見模塊系統文檔。
關於模塊系統的更多信息可參見模塊 。
setTimeout(cb, ms)#
在至少ms
毫秒後調用回調cb
。實際延遲取決於外部因素,如操做系統定時器粒度及系統負載。
超時值必須在1-2147483647的範圍內(包含1和2147483647)。若是該值超出範圍,則該值被看成1毫秒處理。通常來講,一個定時器不能超過24.8天。
返回一個表明該定時器的句柄值。
clearTimeout(t)#
中止一個以前經過setTimeout()
建立的定時器。回調不會再被執行。
setInterval(cb, ms)#
每隔ms
毫秒重複調用回調cb
。注意,取決於外部因素,如操做系統定時器粒度及系統負載,實際間隔可能會改變。它不會少於ms
但可能比ms
長。
間隔值必須在1-2147483647的範圍內(包含1和2147483647)。若是該值超出範圍,則該值被看成1毫秒處理。通常來講,一個定時器不能超過24.8天。
返回一個表明該定時器的句柄值。
clearInterval(t)#
中止一個以前經過setInterval()
建立的定時器。回調不會再被執行。
定製器函數是全局變量。見定時器章節。
控制檯#
穩定度: 4 - 凍結
- {Object}
用於向 stdout 和 stderr 打印字符。相似於大部分 Web 瀏覽器提供的 console 對象函數,在這裏則是輸出到 stdout 或 stderr。
當輸出目標是一個終端或者文件時,console函數是同步的(爲了防止過早退出時丟失信息).當輸出目標是一個管道時它們是異步的(防止阻塞過長時間).
也就是說,在下面的例子中,stdout 是非阻塞的,而 stderr 則是阻塞的。
$ node script.js 2> error.log | tee info.log
在平常使用中,您不須要太擔憂阻塞/非阻塞的差異,除非您須要記錄大量數據。
console.log([data], [...])#
向 stdout 打印並新起一行。這個函數能夠像 printf()
那樣接受多個參數,例如:
console.log('count: %d', count);
若是在第一個字符串中沒有找到格式化元素,那麼 util.inspect
將被應用到各個參數。詳見 util.format()。
console.info([data], [...])#
同 console.log
。
console.error([data], [...])#
同 console.log
,但輸出到 stderr。
console.warn([data], [...])#
同 console.error
。
console.dir(obj)#
對 obj
使用 util.inspect
並將結果字符串輸出到 stdout。這個函數會忽略 obj
上的任何自定義 inspect()
。
console.time(label)#
標記一個時間點。
console.timeEnd(label)#
結束計時器,記錄輸出。例如:
console.time('100-elements'); for (var i = 0; i < 100; i++) { ; } console.timeEnd('100-elements');
console.trace(label)#
打印當前位置的棧跟蹤到 stderr。
console.assert(expression, [message])#
與 assert.ok() 相同,若是 expression
執行結果爲 false
則拋出一個帶上 message
的 AssertionError。
定時器#
穩定度: 5 - 已鎖定
全部的定時器函數都是全局變量. 你使用這些函數時不須要 require()
模塊.
setTimeout(callback, delay, [arg], [...])#
調度 delay
毫秒後的一次 callback
執行。返回一個可能被 clearTimeout()
用到的 timeoutId
。可選地,您還能給回調傳入參數。
請務必注意,您的回調有可能不會在準確的 delay
毫秒後被調用。Node.js 不保證回調被觸發的精確時間和順序。回調會在儘量接近所指定時間上被調用。
clearTimeout(timeoutId)#
阻止一個 timeout 被觸發。
setInterval(callback, delay, [arg], [...])#
調度每隔 delay
毫秒執行一次的 callback
。返回一個可能被 clearInterval()
用到的 intervalId
。可選地,您還能給回調傳入參數。
clearInterval(intervalId)#
中止一個 interval 的觸發。
unref()#
setTimeout
和 setInterval
所返回的值同時具備 timer.unref()
方法,容許您建立一個活動的、但當它是事件循環中僅剩的項目時不會保持程序運行的定時器。若是定時器已被 unref
,再次調用 unref
不會產生其它影響。
在 setTimeout
的情景中當您 unref
您會建立另外一個定時器,並喚醒事件循環。建立太多這種定時器可能會影響事件循環的性能,慎用。
ref()#
若是您以前 unref()
了一個定時器,您能夠調用 ref()
來明確要求定時器讓程序保持運行。若是定時器已被 ref
那麼再次調用 ref
不會產生其它影響。
setImmediate(callback, [arg], [...])#
調度在全部 I/O 事件回調以後、setTimeout
和 setInterval
以前「當即」執行 callback
。返回一個可能被 clearImmediate()
用到的 immediateId
。可選地,您還能給回調傳入參數。
immediate 的回調以它們建立的順序被加入隊列。整個回調隊列會在每一個事件循環迭代中被處理。若是您在一個正被執行的回調中添加 immediate,那麼這個 immediate 在下一個事件循環迭代以前都不會被觸發。
clearImmediate(immediateId)#
中止一個 immediate 的觸發。
Modules#
穩定度: 5 - 已鎖定
Node有一個簡易的模塊加載系統。在node中,文件和模塊是一一對應的。下面示例是foo.js
加載同一目錄下的circle.js
。
foo.js
的內容:
var circle = require('./circle.js'); console.log( 'The area of a circle of radius 4 is ' + circle.area(4));
circle.js
的內容:
var PI = Math.PI; exports.area = function (r) { return PI * r * r; }; exports.circumference = function (r) { return 2 * PI * r; };
circle.js
模塊輸出了area()
和circumference()
兩個函數。要輸出某個對象,把它加到exports
這個特殊對象下便可。
注意,exports
是module.exports
的一個引用,只是爲了用起來方便。當你想輸出的是例如構造函數這樣的單個項目,那麼須要使用module.exports
。
// 正確輸出構造函數 module.exports = MyConstructor;
模塊內的本地變量是私有的。在這裏例子中,PI
這個變量就是circle.js
私有的。
模塊系統的實如今require("module")
中。
循環#
當存在循環的require()
調用時,一個模塊可能在返回時並不會被執行。
考慮這樣一種情形:
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);
首先main.js
加載a.js
,接着a.js
又去加載b.js
。這時,b.js
會嘗試去加載a.js
。爲了防止無限的循環,a.js
會返回一個unfinished copy給b.js
。而後b.js
就會中止加載,並將其exports
對象返回給a.js
模塊。
這樣main.js
就把這兩個模塊都加載完成了。這段程序的輸出以下:
$ 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
若是你的程序中有循環的模塊依賴,請確保工做正常。
核心模塊#
Node中有一些模塊是編譯成二進制的。這些模塊在本文檔的其餘地方有更詳細的描述。
核心模塊定義在node源代碼的lib/
目錄下。
require()
老是會優先加載核心模塊。例如,require('http')
老是返回編譯好的HTTP模塊,而無論是否有這個名字的文件。
文件模塊#
若是按文件名沒有查找到,那麼node會添加 .js
和 .json
後綴名,再嘗試加載,若是仍是沒有找到,最後會加上.node
的後綴名再次嘗試加載。
.js
會被解析爲Javascript純文本文件,.json
會被解析爲JSON格式的純文本文件. .node
則會被解析爲編譯後的插件模塊,由dlopen
進行加載。
模塊以'/'
爲前綴,則表示絕對路徑。例如,require('/home/marco/foo.js')
,加載的是/home/marco/foo.js
這個文件。
模塊以'./'
爲前綴,則路徑是相對於調用require()
的文件。 也就是說,circle.js
必須和foo.js
在同一目錄下,require('./circle')
才能找到。
當沒有以'/'或者'./'來指向一個文件時,這個模塊要麼是"核心模塊",要麼就是從node_modules
文件夾加載的。
若是指定的路徑不存在,require()
會拋出一個code
屬性爲'MODULE_NOT_FOUND'
的錯誤。
從node_modules
文件夾中加載#
若是require()
中的模塊名不是一個本地模塊,也沒有以'/'
, '../'
, 或是 './'
開頭,那麼node會從當前模塊的父目錄開始,嘗試在它的/node_modules
文件夾里加載相應模塊。
若是沒有找到,那麼就再向上移動到父目錄,直到到達頂層目錄位置。
例如,若是位於'/home/ry/projects/foo.js'
的文件調用了require('bar.js')
,那麼node查找的位置依次爲:
/home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
這就要求程序員應儘可能把依賴放在就近的位置,以防崩潰。
Folders as Modules#
能夠把程序和庫放到一個單獨的文件夾裏,並提供單一入口來指向它。有三種方法,使一個文件夾能夠做爲require()
的參數來加載。
首先是在文件夾的根目錄建立一個叫作package.json
的文件,它須要指定一個main
模塊。下面是一個package.json文件的示例。
{ "name" : "some-library", "main" : "./lib/some-library.js" }
示例中這個文件,若是是放在./some-library
目錄下面,那麼require('./some-library')
就將會去加載./some-library/lib/some-library.js
。
This is the extent of Node's awareness of package.json files.
若是目錄裏沒有package.json這個文件,那麼node就會嘗試去加載這個路徑下的index.js
或者index.node
。例如,若上面例子中,沒有package.json,那麼require('./some-library')
就將嘗試加載下面的文件:
./some-library/index.js
./some-library/index.node
Caching#
模塊在第一次加載後會被緩存。這意味着(相似其餘緩存)每次調用require('foo')
的時候都會返回同一個對象,固然,必須是每次都解析到同一個文件。
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.
若是你但願一個模塊屢次執行,那麼就輸出一個函數,而後調用這個函數。
Module Caching Caveats#
模塊的緩存是依賴於解析後的文件名。因爲隨着調用的位置不一樣,可能解析到不一樣的文件(好比需從node_modules
文件夾加載的狀況),因此,若是解析到其餘文件時,就不能保證require('foo')
老是會返回確切的同一對象。
The module
Object#
- {Object}
在每個模塊中,變量 module
是一個表明當前模塊的對象的引用。 特別地,module.exports
能夠經過全局模塊對象 exports
獲取到。 module
不是事實上的全局對象,而更像是每一個模塊內部的。
module.exports#
- {Object}
module.exports
對象是經過模塊系統產生的。有時候這是難以接受的,許多人想讓他們的模塊是某個類的實例。 所以,將要導出的對象賦值給 module.exports
。例如,假設咱們有一個模塊稱之爲 a.js
// Do some work, and after some time emit // the 'ready' event from the module itself. setTimeout(function() { module.exports.emit('ready'); }, 1000);
那麼,在另外一個文件中咱們能夠這樣寫
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);
module.require(id)#
id
{String}- Return: {Object} 已解析模塊的
module.exports
module.require
方法提供了一種像 require()
同樣從最初的模塊加載一個模塊的方法。
注意,爲了這樣作,你必須取得一個對 module
對象的引用。 require()
返回 module.exports
,而且 module
是一個典型的只能在特定模塊做用域內有效的變量,若是要使用它,就必須明確的導出。
module.id#
- {String}
用於區別模塊的標識符。一般是徹底解析後的文件名。
module.filename#
- {String}
模塊徹底解析後的文件名。
module.loaded#
- {Boolean}
不論該模塊是否加載完畢,或者正在加載的過程當中。
module.parent#
- {Module Object}
引入這個模塊的模塊。
module.children#
- {Array}
這個模塊引入的全部模塊對象。
整體來講...#
爲了獲取調用 require
加載的確切的文件名,使用 require.resolve()
函數。
綜上所述,下面用僞代碼的高級算法形式表達了 require.resolve 是如何工做的:
NODE_MODULES_PATHS(START) 1. let PARTS = path split(START) 2. let ROOT = index of first instance of "node_modules" in PARTS, or 0 3. let I = count of PARTS - 1 4. let DIRS = [] 5. while I > ROOT, 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 6. return DIRS
從全局文件夾加載#
若是 NODE_PATH
環境變量設置爲一個以冒號分割的絕對路徑的列表, 找不到模塊時 node 將會從這些路徑中搜索模塊。 (注意:在 windows 操做系統上,NODE_PATH
是以分號間隔的)
此外,node 將會搜索如下地址:
- 1:
$HOME/.node_modules
- 2:
$HOME/.node_libraries
- 3:
$PREFIX/lib/node
$HOME
是用戶的主目錄,$PREFIX
是 node 裏配置的 node_prefix
。
這些大可能是因爲歷史緣由。強烈建議讀者將所依賴的模塊放到 node_modules
文件夾裏。 這樣加載的更快也更可靠。
訪問主模塊#
當 Node 直接運行一個文件時,require.main
就被設置爲它的 module
。 也就是說你能夠判斷一個文件是不是直接被運行的
require.main === module
對於一個 foo.js
文件,若是經過 node foo.js
運行是 true
,可是經過 require('./foo')
運行倒是 false
。
由於 module
提供了一個 filename
屬性(一般等於 __filename
), 因此當前程序的入口點能夠經過 require.main.filename
來獲取。
附錄: 包管理技巧#
Node 的 require()
函數的語義被設計的足夠通用化,以支持各類常規目錄結構。 包管理程序如 dpkg,rpm 和 npm 將不用修改就可以從 Node 模塊構建本地包。
接下來咱們將給你一個可行的目錄結構建議:
假設咱們但願將一個包的指定版本放在 /usr/lib/node/<some-package>/<some-version>
目錄中。
包能夠依賴於其餘包。爲了安裝包 foo,可能須要安裝包 bar 的一個指定版本。 包 bar 也可能有依賴關係,在某些狀況下依賴關係可能發生衝突或者造成循環。
由於 Node 會查找它所加載的模塊的真實路徑(也就是說會解析符號連接), 而後按照上文描述的方式在 node_modules 目錄中尋找依賴關係,這種情形跟如下體系結構很是相像:
- /usr/lib/node/foo/1.2.3/ - foo 包 1.2.3 版本的內容
- /usr/lib/node/bar/4.3.2/ - foo 包所依賴的 bar 包的內容
- /usr/lib/node/foo/1.2.3/node_modules/bar - 指向 /usr/lib/node/bar/4.3.2/ 的符號連接
- /usr/lib/node/bar/4.3.2/node_modules/* - 指向 bar 包所依賴的包的符號連接
所以即使存在循環依賴或依賴衝突,每一個模塊仍是能夠得到他所依賴的包的一個可用版本。
當 foo 包中的代碼調用 require('bar'),將得到符號連接 /usr/lib/node/foo/1.2.3/node_modules/bar
指向的版本。 而後,當 bar 包中的代碼調用 require('queue')
,將會得到符號連接 /usr/lib/node/bar/4.3.2/node_modules/quux
指向的版本。
此外,爲了進一步優化模塊搜索過程,不要將包直接放在 /usr/lib/node
目錄中,而是將它們放在 /usr/lib/node_modules/<name>/<version>
目錄中。 這樣在依賴的包找不到的狀況下,就不會一直尋找 /usr/node_modules
目錄或 /node_modules
目錄了。
爲了使模塊在 node 的 REPL 中可用,你可能須要將 /usr/lib/node_modules
目錄加入到 $NODE_PATH
環境變量中。 因爲在 node_modules 目錄中搜索模塊使用的是相對路徑,基於調用 require()
的文件所在真實路徑,所以包自己能夠放在任何位置。
Addons插件#
Addons插件就是動態鏈接庫。它相似膠水,將c、c++和Node粘貼起來。它的API(目前來講)至關複雜,涉及到了幾個類庫的知識。
- V8 JavaScript引擎,一個 C++ 類庫. 用於和JavaScript進行交互的接口。 建立對象, 調用函數等. 文檔大部分在這裏:
v8.h
頭文件 (deps/v8/include/v8.h
在Node源代碼目錄裏), 也有可用的線上文檔 線上. (譯者:想要學習c++的addons插件編寫,必須先了解v8的接口)
- libuv, C語言編寫的事件循環類庫。任什麼時候候須要等待一個文件描述符變爲可讀狀態,等待一個定時器,或者等待一個接受信號都須要使用libuv類庫的接口。也就是說,若是你執行任何I/O操做,libuv類庫將會被用到。
- 內部 Node 類庫.最重要的接口就是
node::ObjectWrap
類,這個類你應該是最可能想要派生的。
- 其餘.請參閱
deps/
得到更多可用類庫。
Node 靜態編譯了全部依賴到它的可執行文件中去了。當編譯你的模塊時,你沒必要擔憂沒法鏈接上述那些類庫。 (譯者:換而言之,你在編譯本身的addons插件時,只管在頭部 #include <uv.h>,沒必要在binding.gyp中聲明)
下面全部的例子均可如下載到: 下載 這或許能成爲你學習和創做本身addon插件的起點。
Hello world(世界你好)#
做爲開始,讓咱們用編寫一個小的addon插件,這個addon插件的c++代碼至關於下面的JavaScript代碼。
module.exports.hello = function() { return 'world'; };
首先咱們建立一個 hello.cc
文件:
NODE_MODULE(hello, init)//譯者:將addon插件名hello和上述init函數關聯輸出
注意全部Node的addons插件都必須輸出一個初始化函數:
void Initialize (Handle<Object> exports); NODE_MODULE(module_name, Initialize)
在NODE_MODULE
以後沒有分號,由於它不是一個函數(請參閱node.h
)
這個module_name
(模塊名)須要和最後編譯生成的2進制文件名(減去.node後綴名)相同。
源代碼須要生成在hello.node
,這個2進制addon插件中。 須要作到這些,咱們要建立一個名爲binding.gyp
的文件,它描述了建立這個模塊的配置,而且它的格式是相似JSON的。 文件將被命令:node-gyp 編譯。
{ "targets": [ { "target_name": "hello", //譯者:addon插件名,注意這裏的名字必需和上面NODE_MODULE中的一致 "sources": [ "hello.cc" ] //譯者:這是須要編譯的源文件 } ] }
下一步是根據當前的操做系統平臺,利用node-gyp configure
命令,生成合適的項目文件。
如今你會有一個Makefile
(在Unix平臺) 或者一個 vcxproj
file (在Windows上),它們都在build/
文件夾中. 而後執行命令 node-gyp build
進行編譯。 (譯者:固然你能夠執行 node-gyp rebuild
一步搞定)
如今你已經有了編譯好的 .node
文件了,這個編譯好的綁定文件會在目錄 build/Release/
下
如今你能夠使用這個2進制addon插件在Node項目hello.js
中了,經過指明require
這個剛剛建立的hello.node
模塊使用它。
console.log(addon.hello()); // 'world'
請閱讀下面的內容得到更多詳情或者訪問https://github.com/arturadib/node-qt獲取一個生產環境的例子。
Addon patterns(插件方式)#
下面是一些幫助你開始編寫addon插件的方式。參考這個在線的v8 手冊用來幫助你調用各類v8接口, 而後是v8的 嵌入式開發嚮導 ,解釋幾個概念,如 handles, scopes,function templates等。
爲了能跑起來這些例子,你必須用 node-gyp
來編譯他們。 建立一個binding.gyp
文件:
{ "targets": [ { "target_name": "addon", "sources": [ "addon.cc" ] } ] }
事實上能夠有多個 .cc
文件, 就簡單的在 sources
數組裏加上便可,例子:
"sources": ["addon.cc", "myexample.cc"]
如今你有了你的binding.gyp
文件了,你可要開始執行configure 和 build 命令構建你的addon插件了
$ node-gyp configure build
Function arguments(函數參數)#
下面的部分說明了如何從JavaScript的函數調用得到參數而後返回一個值。這是主要的內容而且僅須要源代碼addon.cc
。
NODE_MODULE(addon, Init)
你能夠使用下面的JavaScript代碼片斷來測試它
console.log( 'This should be eight:', addon.add(3,5) );
Callbacks(回調)#
你能夠傳遞JavaScript functions 到一個C++ function 而且執行他們,這裏是 addon.cc
文件:
NODE_MODULE(addon, Init)
注意這個例子對Init()
使用了兩個參數,將完整的 module
對象做爲第二個參數傳入。這容許addon插件徹底的重寫 exports
,這樣就能夠用一個函數代替多個函數做爲exports
的屬性了。
你能夠使用下面的JavaScript代碼片斷來測試它
addon(function(msg){ console.log(msg); // 'hello world' });
Object factory(對象工廠)#
在這個addon.cc
文件裏用一個c++函數,你能夠建立而且返回一個新的對象,這個新的對象擁有一個msg的屬性,它的值是經過createObject()方法傳入的
NODE_MODULE(addon, Init)
在js中測試以下:
var obj1 = addon('hello'); var obj2 = addon('world'); console.log(obj1.msg+' '+obj2.msg); // 'hello world'
Function factory(函數工廠)#
此次將展現如何建立並返回一個JavaScript function函數,這個函數實際上是經過c++包裝的。
NODE_MODULE(addon, Init)
測試它:
var fn = addon(); console.log(fn()); // 'hello world'
Wrapping C++ objects(包裝c++對象)#
這裏將建立一個被c++包裹的對象或類MyObject
,它是能夠在JavaScript中經過new
操做符實例化的。 首先咱們要準備主要的模塊文件addon.cc
:
NODE_MODULE(addon, InitAll)
而後在myobject.h
文件中建立你的包裝類,它繼承自 node::ObjectWrap
:
#endif
在文件 myobject.cc
能夠實施各類你想要暴露給js的方法。 這裏咱們暴露方法名爲 plusOne
給就是,它表示將構造函數的屬性加1.
return scope.Close(Number::New(obj->counter_)); }
測試它:
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(工廠包裝對象)#
這是很是有用的,當你想建立原生的JavaScript對象時,又不想明確的使用JavaScript的new
操做符。
var obj = addon.createObject(); // 用上面的方式代替下面的: // var obj = new addon.Object();
讓咱們註冊在 addon.cc
文件中註冊createObject
方法:
NODE_MODULE(addon, InitAll)
在myobject.h
文件中,咱們如今介紹靜態方法NewInstance,它可以實例化對象(舉個例子,它的工做就像是 在JavaScript中的
new` 操做符。)
#endif
這裏的處理方式和上面的 myobject.cc
很像:
return scope.Close(Number::New(obj->counter_)); }
測試它:
var obj2 = createObject(20); console.log( obj2.plusOne() ); // 21 console.log( obj2.plusOne() ); // 22 console.log( obj2.plusOne() ); // 23
Passing wrapped objects around(傳遞包裝的對象)#
除了包裝和返回c++對象之外,你能夠傳遞他們而且經過Node的node::ObjectWrap::Unwrap
幫助函數解包裝他們。 在下面的addon.cc
文件中,咱們介紹了一個函數add()
,它可以獲取2個MyObject
對象。
NODE_MODULE(addon, InitAll)
爲了使事情變得有趣,咱們在 myobject.h
採用一個公共的方法,因此咱們可以在unwrapping解包裝對象以後使用私有成員的值。
#endif
myobject.cc
文件的處理方式和前面相似
return scope.Close(instance); }
測試它:
var obj1 = addon.createObject(10); var obj2 = addon.createObject(20); var result = addon.add(obj1, obj2);
console.log(result); // 30
process#
process
對象是一個全局對象,能夠在任何地方訪問到它。 它是EventEmitter的一個實例。
Exit Codes#
Node 執行程序正常狀況下會返回 0,這也意味着,包括全部「異步」在內的操做都已結束。(筆者注:linux terminal 下使用 echo $? 查看,win cmd 下使用 echo %ERRORLEVEL% 查看)除此以外的其餘返回狀態以下:
1
未捕獲的致命異常(Uncaught Fatal Exception) - There was an uncaught exception, and it was not handled by a domain or anuncaughtException
event handler.2
- 未使用(Unused) (reserved by Bash for builtin misuse)3
解析錯誤(Internal JavaScript Parse Error) - The JavaScript source code internal in Node's bootstrapping process caused a parse error. This is extremely rare, and generally can only happen during development of Node itself.4
評估失敗(Internal JavaScript Evaluation Failure) - The JavaScript source code internal in Node's bootstrapping process failed to return a function value when evaluated. This is extremely rare, and generally can only happen during development of Node itself.5
致命錯誤(Fatal Error) - There was a fatal unrecoverable error in V8. Typically a message will be printed to stderr with the prefixFATAL ERROR
.6
未正確的異常處理(Non-function Internal Exception Handler) - There was an uncaught exception, but the internal fatal exception handler function was somehow set to a non-function, and could not be called.7
異常處理函數運行時失敗(Internal Exception Handler Run-Time Failure) - There was an uncaught exception, and the internal fatal exception handler function itself threw an error while attempting to handle it. This can happen, for example, if aprocess.on('uncaughtException')
ordomain.on('error')
handler throws an error.8
- 未使用(Unused). In previous versions of Node, exit code 8 sometimes indicated an uncaught exception.9
- 無效的參數(Invalid Argument) - Either an unknown option was specified, or an option requiring a value was provided without a value.10
運行時失敗(Internal JavaScript Run-Time Failure) - The JavaScript source code internal in Node's bootstrapping process threw an error when the bootstrapping function was called. This is extremely rare, and generally can only happen during development of Node itself.12
無效的調試參數(Invalid Debug Argument) - The--debug
and/or--debug-brk
options were set, but an invalid port number was chosen.>128
信號退出(Signal Exits) - If Node receives a fatal signal such asSIGKILL
orSIGHUP
, then its exit code will be128
plus the value of the signal code. This is a standard Unix practice, since exit codes are defined to be 7-bit integers, and signal exits set the high-order bit, and then contain the value of the signal code.
事件: 'exit'#
當進程將要退出時觸發。這是一個在固定時間檢查模塊狀態(如單元測試)的好時機。須要注意的是 'exit' 的回調結束後,主事件循環將再也不運行,因此計時器也會失效。
監聽 exit
事件的例子:
process.on('exit', function() { // 設置一個延遲執行 setTimeout(function() { console.log('主事件循環已中止,因此不會執行'); }, 0); console.log('退出前執行'); });
事件: 'uncaughtException'(未捕獲錯誤)#
當一個異常冒泡迴歸到事件循環中就會觸發這個事件,若是創建了一個監聽器來監聽這個異常,默認的行爲(打印堆棧跟蹤信息並退出)就不會發生。
監聽 uncaughtException
示例:
// 故意製造一個異常,並且不catch捕獲它. nonexistentFunc(); console.log('This will not run.');
注意,uncaughtException
未捕獲異常是一個很是粗略的異常處理。
儘可能不要使用它,使用 domains 來代替它,若是你已經使用了,請在不處理這個異常以後重啓你的應用。
請 不要 象使用node.js的有錯誤回覆執行
這樣使用.一個未處理異常意味着你的應用和你的擴展Node.js自身是有未知狀態的。盲目的恢復意味着任何事情均可能發生。
你在升級的系統時拉掉了電源線,而後恢復了。可能10次裏有9次每一偶問題,可是第10次,你的系統就會崩潰。
你已經被警告。
Signal Events#
當進程接收到信號時觸發。信號列表詳見 POSIX 標準的 sigaction(2)如 SIGINT、SIGUSR1 等。
監聽 SIGINT
信號的示例:
// 設置 'SIGINT' 信號觸發事件 process.on('SIGINT', function() { console.log('收到 SIGINT 信號。 退出請使用 Ctrl + D '); });
在大多數終端下,一個發送 SIGINT
信號的簡單方法是按下 ctrl + c
。
process.stdout#
一個指向標準輸出流(stdout)
的 可寫的流(Writable Stream)
。
舉例: console.log
的實現
console.log = function(d) { process.stdout.write(d + '\n'); };
process.stderr 和 process.stdout 不像 Node 中其餘的流(Streams) 那樣,他們一般是阻塞式的寫入。當其引用指向 普通文件
或者 TTY文件描述符
時他們就是阻塞的(注:TTY 能夠理解爲終端的一種,可聯想 PuTTY,詳見百科)。當他們引用指向管道(pipes)時,他們就同其餘的流(Streams)同樣是非阻塞的。
要檢查 Node 是否正在運行一個 TTY上下文 中(注:linux 中沒有運行在 tty 下的進程是 守護進程
),能夠用使用 process.stderr、process.stdout 或 process.stdin 的 isTTY 屬性:
$ node -p "Boolean(process.stdout.isTTY)" true $ node -p "Boolean(process.stdout.isTTY)" | cat false
更多信息,請查看 tty 文檔。
process.stderr#
一個指向標準錯誤流(stderr)的 可寫的流(Writable Stream)。
process.stderr 和 process.stdout 不像 Node 中其餘的流(Streams) 那樣,他們一般是阻塞式的寫入。當其引用指向 普通文件
或者 TTY文件描述符
時他們就是阻塞的(注:TTY 能夠理解爲終端的一種,可聯想 PuTTY,詳見百科)。當他們引用指向管道(pipes)時,他們就同其餘的流(Streams)同樣是非阻塞的。
process.stdin#
一個指向 標準輸入流(stdin) 的可讀流(Readable Stream)。標準輸入流默認是暫停 (pause) 的,因此必需要調用 process.stdin.resume() 來恢復 (resume) 接收。
打開標準輸入流,並監聽兩個事件的示例:
process.stdin.on('end', function() { process.stdout.write('end'); }); // gets 函數的簡單實現 function gets(cb){ process.stdin.resume(); process.stdin.setEncoding('utf8'); process.stdin.on('data', function(chunk) { process.stdin.pause(); cb(chunk); }); } gets(function(reuslt){ console.log("["+reuslt+"]"); });
process.argv#
一個包含命令行參數的數組。第一個元素會是 'node', 第二個元素將是 .Js 文件的名稱。接下來的元素依次是命令行傳入的參數。
// 打印 process.argv process.argv.forEach(function(val, index, array) { console.log(index + ': ' + val); });
輸出將會是:
$ 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#
開啓當前進程的這個可執行文件的絕對路徑。
示例:
/usr/local/bin/node
process.execArgv#
與 process.argv
相似,不過是用於保存 node特殊(node-specific) 的命令行選項(參數)。這些特殊的選項不會出如今 process.argv
中,並且 process.execArgv 不會保存 process.argv
中保存的參數(如 0:node 1:文件名 2.3.4.參數 等), 全部文件名以後的參數都會被忽視。這些選項能夠用於派生與與父進程相同執行環境的子進程。
示例:
$ node --harmony script.js --version
process.execArgv 中的特殊選項:
['--harmony']
process.argv 接收到的參數:
['/usr/local/bin/node', 'script.js', '--version']
process.abort()#
這將致使 Node 觸發一個abort事件,這會致使Node退出而且建立一個核心文件。
process.chdir(directory)#
改變進程的當前進程的工做目錄,若操做失敗則拋出異常。
console.log('當前目錄:' + process.cwd()); try { process.chdir('/tmp'); console.log('新目錄:' + process.cwd()); } catch (err) { console.log('chdir: ' + err); }
process.cwd()#
返回進程當前的工做目錄。
console.log('當前目錄:' + process.cwd());
process.env#
一個包括用戶環境的對象。詳細參見 environ(7)。
process.exit([code])#
終止當前進程並返回給定的 code
。若是省略了 code
,退出是會默認返回成功的狀態碼('success' code) 也就是 0
。
退出並返回失敗的狀態 ('failure' code):
process.exit(1);
執行上述代碼,用來執行 node 的 shell 就能收到值爲 1 的 exit code
process.exitCode#
當進程既正常退出,或者經過未指定 code 的 process.exit()
退出時,這個屬性中所存儲的數字將會成爲進程退出的錯誤碼 (exit code)。
若是指名了 process.exit(code)
中退出的錯誤碼 (code),則會覆蓋掉 process.exitCode
的設置。
process.getgid()#
注意: 該函數僅適用於遵循 POSIX 標準的系統平臺如 Unix、Linux等 而 Windows、 Android 等則不適用。
獲取進程的羣組標識(詳見getgid(2))。獲取到的是羣組的數字ID,不是羣組名稱。
if (process.getgid) { console.log('當前 gid: ' + process.getgid()); }
process.setgid(id)#
注意: 該函數僅適用於遵循 POSIX 標準的系統平臺如 Unix、Linux等 而 Windows、 Android 等則不適用。
設置進程的羣組標識(詳見getgid(2))。參數能夠是一個數字ID或者羣組名字符串。若是指定了一個羣組名,這個方法會阻塞等待將羣組名解析爲數字ID。
if (process.getgid && process.setgid) { console.log('當前 gid: ' + process.getgid()); try { process.setgid(501); console.log('新 gid: ' + process.getgid()); } catch (err) { console.log('設置 gid 失敗: ' + err); } }
process.getuid()#
注意: 該函數僅適用於遵循 POSIX 標準的系統平臺如 Unix、Linux等 而 Windows、 Android 等則不適用。
獲取執行進程的用戶ID(詳見getgid(2))。這是用戶的數字ID,不是用戶名。
if (process.getuid) { console.log('當前 uid: ' + process.getuid()); }
process.setuid(id)#
注意: 該函數僅適用於遵循 POSIX 標準的系統平臺如 Unix、Linux等 而 Windows、 Android 等則不適用。
設置執行進程的用戶ID(詳見getgid(2))。參數能夠使一個數字ID或者用戶名字符串。若是指定了一個用戶名,那麼該方法會阻塞等待將用戶名解析爲數字ID。
if (process.getuid && process.setuid) { console.log('當前 uid: ' + process.getuid()); try { process.setuid(501); console.log('新 uid: ' + process.getuid()); } catch (err) { console.log('設置 uid 失敗: ' + err); } }
process.getgroups()#
注意: 該函數僅適用於遵循 POSIX 標準的系統平臺如 Unix、Linux等 而 Windows、 Android 等則不適用。
返回一個保存補充組ID(supplementary group ID)的數組。POSIX 標準沒有指名 若是有效組 ID(effective group ID)被包括在內的狀況,而在 node.js 中則確保它始終是。(POSIX leaves it unspecified if the effective group ID is included but node.js ensures it always is. )
process.setgroups(groups)#
注意: 該函數僅適用於遵循 POSIX 標準的系統平臺如 Unix、Linux等 而 Windows、 Android 等則不適用。
設置補充分組的ID標識. 這是一個特殊的操做, 意味着你必須擁有root或者CAP_SETGID權限才能夠。(譯者:CAP_SETGID表示設定程序容許普通用戶使用setgid函數,這與文件的setgid權限位無關)
這個列表能夠包括分組的ID表示,或分組名或二者都有。
process.initgroups(user, extra_group)#
注意: 該函數僅適用於遵循 POSIX 標準的系統平臺如 Unix、Linux等 而 Windows、 Android 等則不適用。
讀取 /etc/group 而且初始化group分組訪問列表,使用改爲員所在的全部分組, 這是一個特殊的操做, 意味着你必須擁有root或者CAP_SETGID權限才能夠。
user
是一個用戶名或者用戶ID. extra_group
是分組的組名或者分組ID。
有時候,當你在註銷權限 (dropping privileges) 的時候須要注意。例如:
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#
一個暴露編譯時存儲版本信息的內置變量 NODE_VERSION
的屬性。
console.log('版本: ' + process.version);
process.versions#
一個暴露存儲 node 以及其依賴包 版本信息的屬性。
console.log(process.versions);
輸出:
{ 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#
一個包含用來編譯當前 node.exe 的配置選項的對象。內容與運行 ./configure
腳本生成的 "config.gypi" 文件相同。
最可能的輸出示例以下:
{ 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])#
向進程發送一個信號。 pid
是進程的 id 而 signal
則是描述信號的字符串名稱。信號的名稱都形似 'SIGINT' 或者 'SIGUSR1'。若是沒有指定參數則會默認發送 'SIGTERM' 信號,更多信息請查看 kill(2) 。
值得注意的是,這個函數的名稱雖然是 process.kill
, 但就像 kill
系統調用(詳見《Unix高級編程》)同樣,它僅僅只是一個信號發送器。而信號的發送不只僅只是用來殺死(kill)目標進程。
向當前進程發送信號的示例:
process.kill(process.pid, 'SIGHUP');
process.pid#
當前進程的 PID
console.log('當前進程 id: ' + process.pid);
process.title#
獲取/設置 (Getter/setter) 'ps' 中顯示的進程名。
當設置該屬性時,所能設置的字符串最大長度視具體平臺而定,若是超過的話會自動截斷。
在 Linux 和 OS X 上,它受限於名稱的字節長度加上命令行參數的長度,由於它有覆蓋參數內存(argv memory)。
v0.8 版本容許更長的進程標題字符串,也支持覆蓋環境內存,可是存在潛在的不安全和混亂(很難說清楚)。
process.arch#
返回當前 CPU 處理器的架構:'arm'、'ia32' 或者 'x64'.
console.log('當前CPU架構是:' + process.arch);
process.platform#
返回當前程序運行的平臺:'darwin'
, 'freebsd'
, 'linux'
, 'sunos'
或者 'win32'
console.log('當前系統平臺是: ' + process.platform);
process.memoryUsage()#
返回一個對象,它描述了Node進程的內存使用狀況單位是bytes。
console.log(util.inspect(process.memoryUsage()));
輸出將會是:
{ rss: 4935680, heapTotal: 1826816, heapUsed: 650472 }
heapTotal
和 heapUsed
是根據 V8引擎的內存使用狀況來的
process.nextTick(callback)#
callback
{Function}
在事件循環的下一次循環中調用 callback 回調函數。
這 不是 setTimeout(fn, 0)
函數的一個簡單別名,由於它的效率高多了。該函數能在任何 I/O 事前以前調用咱們的回調函數。可是這個函數在層次超過某個限制的時候,也會出現瑕疵,詳細見 process.maxTickDepth
。
console.log('開始'); process.nextTick(function() { console.log('nextTick 回調'); }); console.log('已設定'); // 輸出: // 開始 // 已設定 // nextTick 回調
若是你想要在【對象建立】以後而【I/O 操做】發生以前執行某些操做,那麼這個函數對你而言就十分重要了。
// thing.startDoingStuff() 如今被調用了, 而不是以前.
【注意!!】保證你的函數必定是同步執行或者必定是異步執行,這很是重要!!參考以下的例子:
fs.stat('file', cb); }
這樣執行是很危險。若是你還不清楚上述行爲的危害請看下面的例子:
maybeSync(true, function() { foo(); }); bar();
那麼,使用剛纔那個不知道是同步仍是異步的操做,在編程的時候你就會發現,你不能肯定究竟是 foo() 先執行,仍是 bar() 先執行。
用下面的方法就能夠更好的解決:
fs.stat('file', cb); }
注意:nextTick 的隊列會在徹底執行完畢以後才調用 I/O 操做 (the nextTick queue is completely drained on each pass of the event loop before additional I/O is processed.) 。所以,遞歸設置 nextTick 的回調就像一個 while(true) ;
循環同樣,將會阻止任何 I/O 操做的發生。
process.umask([mask])#
設置或者讀取進程的文件模式的建立掩碼。子進程從父進程中繼承這個掩碼。若是設定了參數 mask 那麼返回舊的掩碼,不然返回當前的掩碼。
oldmask = process.umask(newmask); console.log('原掩碼: ' + oldmask.toString(8) + '\n' '新掩碼: ' + newmask.toString(8));
process.uptime()#
返回 Node 程序已運行的秒數。
process.hrtime()#
返回當前的高分辨時間,形式爲 [秒,納秒]
的元組數組。它是相對於在過去的任意時間。該值與日期無關,所以不受時鐘漂移的影響。主要用途是能夠經過精確的時間間隔,來衡量程序的性能。
你能夠將前一個 process.hrtime()
的結果傳遞給當前的 process.hrtime()
函數,結果會返回一個比較值,用於基準和衡量時間間隔。
console.log('基準相差 %d 納秒', diff[0] * 1e9 + diff[1]); // 基準相差 1000000527 納秒 }, 1000);
utils#
穩定度: 4 - 凍結
若是你想使用模塊 'util'
中已定義的方法. 只需 require('util')
便可使用.
util
模塊設計的主要目的是爲了知足Node內部API的需求 。這個模塊中的不少方法在你編寫Node程序的時候都是頗有幫助的。若是你以爲提供的這些方法知足不了你的需求,那麼咱們鼓勵你編寫本身的實用工具方法。咱們 不但願util
模塊中添加任何對於Node的內部功能非必要的擴展。
util.debuglog(section)#
section
{String} 被調試的程序節點部分- 返回值: {Function} 日誌處理函數
這個方法是在存在NODE_DEBUG
環境變量的基礎上,建立一個有條件寫到stderr裏的函數。若是「節點」的名字出如今這個環境變量裏,那麼就返回一個功能相似於console.error()
的函數.若是不是,那麼返回一個空函數.
例如:
var bar = 123; debuglog('hello from foo [%d]', bar);
<!-- endsection --> <!-- section:841c12a486aeca12985eeae2d550044e --> 若是這個程序以`NODE_DEBUG=foo` 的環境運行,那麼它將會輸出: <!-- endsection --> <!-- section:cefee92825ed4220569779223fcc49f3 --> FOO 3245: hello from foo [123] <!-- endsection --> <!-- section:17ef1e93428ebec32b98fa8fe18e7807 --> `3245`是進程的ID, 若是程序不以剛纔那樣設置的環境變量運行,那麼將不會輸出任何東西。 <!-- endsection --> <!-- section:fb8af07a0bc0e884ec481501fb9ee17d --> 多個`NODE_DEBUG`環境變量,你能夠用逗號進行分割。例如,`NODE_DEBUG= fs, net, tls`。 <!-- endsection --> <!-- section:1785afa5e0b057aea818cd8bc131248a --> ## util.format(format, [...]) <!-- endsection --> <!-- section:91ee7971cb6dbe7c7841d5c0357a625a --> 根據第一個參數,返回一個格式化字符串,相似`printf`的格式化輸出。 <!-- endsection --> <!-- section:eed068a3508e3b9cc687607e97338b9f --> 第一個參數是一個字符串,包含零個或多個*佔位符*。 每個佔位符被替換爲與其對應的轉換後的值。 支持的佔位符有: <!-- endsection --> <!-- section:da9b014604572a67a757e892ddd36dd3 --> * `%s` - 字符串. * `%d` - 數字 (整型和浮點型). * `%j` - JSON. 若是這個參數包含循環對象的引用,將會被替換成字符串 `'[Circular]'`。 * `%%` - 單獨一個百分號(`'%'`)。不會消耗一個參數。 <!-- endsection --> <!-- section:c2996cb0cabc702cd8d2bf9d2410599b --> 若是佔位符沒有相對應的參數,佔位符將不會被替換。 <!-- endsection --> <!-- section:8b6a9f474a82c2495887bf9fe6602308 --> util.format('%s:%s', 'foo'); // 'foo:%s' <!-- endsection --> <!-- section:1e95291ba804f022549694a216ac10c6 --> 若是有多個參數佔位符,額外的參數將會調用`util.inspect()`轉換爲字符串。這些字符串被鏈接在一塊兒,而且以空格分隔。 <!-- endsection --> <!-- section:ba9ecf5f8b441a986c81bee295e7f5f6 --> util.format('%s:%s', 'foo', 'bar', 'baz'); // 'foo:bar baz' <!-- endsection --> <!-- section:f34f71da627ffc546bb170512e2ffa99 --> 若是第一個參數是一個非格式化字符串,那麼`util.format()`將會把全部的參數轉成字符串,以空格隔開,拼接在一塊,並返回該字符串。`util.inspect()`會把每一個參數都轉成一個字符串。 <!-- endsection --> <!-- section:25dcc02c2222a4275231d90579c8598e --> util.format(1, 2, 3); // '1 2 3' <!-- endsection --> <!-- section:f695fcc4f18f5c6e339ccce4e3389dcf --> ## util.log(string) <!-- endsection --> <!-- section:726d139874d57d83bf5da6c193940e4d --> 在控制檯進行輸出,並帶有時間戳。 <!-- endsection --> <!-- section:ba5cd1d0dee4eb1d7de5808ac9c816b8 --> 示例:require('util').log('Timestamped message.'); <!-- endsection --> <!-- section:49290ff385e98b889e7199f35d8fdd82 --> ## util.inspect(object, [options]) <!-- endsection --> <!-- section:1109f4d3eef77037e85144a6ac35edb4 --> 返回一個對象的字符串表現形式, 在代碼調試的時候很是有用. <!-- endsection --> <!-- section:258dc184e5a4c8130e86a263acb47331 --> 能夠經過加入一些可選選項,來改變對象的格式化輸出形式: <!-- endsection --> <!-- section:e8f8d3d45f5ea0449c8466bcc7d1aef5 --> - `showHidden` - 若是設爲 `true`,那麼該對象的不可枚舉的屬性將會被顯示出來。默認爲`false`. <!-- endsection --> <!-- section:961283759790f15496ef9cfd71e80da0 --> - `depth` - 告訴 `inspect` 格式化對象的時候遞歸多少次。這個選項在格式化複雜對象的時候比較有用。 默認爲 `2`。若是想無窮遞歸下去,則賦值爲`null`便可。 <!-- endsection --> <!-- section:87002282463d3e4ae824462785cdb97f --> - `colors` - 若是設爲`true`,將會以`ANSI`顏色代碼風格進行輸出. 默認是`false`。顏色是可定製的,請看下面: <!-- endsection --> <!-- section:e58f864e5d78935059b0d82a0de99ac5 --> - `customInspect` - 若是設爲 `false`,那麼定義在被檢查對象上的`inspect(depth, opts)` 方法將不會被調用。 默認爲`true`。 <!-- endsection --> <!-- section:ba2e5c5a48d29e5af4a12604012adbed