├── GLOSSARY.md ├── .gitignore ├── url ├── README.md ├── url_parsing.md └── url.md ├── os └── README.md ├── querystring ├── README.md └── querystring.md ├── https ├── README.md ├── class_https_Agent.md └── class_https_Server.md ├── v8 ├── README.md └── v8.md ├── process ├── README.md ├── exit_codes.md └── signal_events.md ├── net └── README.md ├── LOG.md ├── cli ├── README.md ├── synopsis.md ├── environment_variables.md └── options.md ├── path └── README.md ├── vm ├── README.md ├── class_Script.md └── vm.md ├── appendix └── README.md ├── modules ├── core_modules.md ├── accessing_the_main_module.md ├── the_module_wrapper.md ├── caching.md ├── file_modules.md ├── loading_from_node_modules_folders.md ├── loading_from_the_global_folders.md ├── folders_as_modules.md ├── cycles.md ├── package_manager_tips.md ├── all_together.md ├── README.md └── module.md ├── debugger ├── watchers.md ├── advanced_usage.md ├── README.md └── commands_reference.md ├── punycode ├── README.md └── punycode.md ├── tls ├── alpn_npn_and_sni.md ├── class_CryptoStream.md ├── class_SecurePair.md ├── client_initiated_renegotiation_attack_mitigation.md ├── perfect_forward_secrecy.md ├── modifying_the_default_tls_cipher_suite.md ├── README.md └── class_tls_Server.md ├── timers ├── class_Immediate.md ├── README.md ├── class_Timeout.md ├── cancelling_timers.md ├── scheduling_timers.md └── timer.md ├── zlib ├── README.md ├── class_options.md ├── memory_usage_tuning.md ├── flushing.md ├── constants.md ├── zlib_class.md ├── examples.md └── zlib.md ├── domain ├── domain.md ├── additions_to_error_objects.md ├── README.md ├── implicit_binding.md ├── explicit_binding.md └── do_not_ignore_errors.md ├── util └── README.md ├── console ├── asynchronous_vs_synchronous_consoles.md └── README.md ├── fs ├── buffer_api.md ├── class_fs_ReadStream.md ├── class_fs_WriteStream.md ├── class_fs_FSWatcher.md ├── README.md └── class_fs_Stats.md ├── child_process ├── maxbuffer_and_unicode.md └── README.md ├── errors ├── exceptions_vs_errors.md ├── class_TypeError.md ├── class_SyntaxError.md ├── class_RangeError.md ├── class_ReferenceError.md ├── README.md ├── system_errors.md ├── error_propagation_and_interception.md └── class_Error.md ├── assert └── README.md ├── globals └── README.md ├── documentation ├── json_output.md ├── stability_index.md ├── syscalls_and_man_pages.md └── README.md ├── buffer ├── buffers_and_es6_iteration.md ├── the_zero_fill_buffers_clo.md ├── buffer.md ├── buffers_and_character_encodings.md ├── README.md ├── class_SlowBuffer.md ├── buffers_and_typedarray.md └── other.md ├── addons ├── native_abstractions_for_nodejs.md ├── README.md └── hello_world.md ├── tty ├── tty.md ├── README.md ├── class_ReadStream.md └── class_WriteStream.md ├── events ├── asynchronous_vs_synchronous.md ├── handling_events_only_once.md ├── passing_arguments_and_this_to_listeners.md ├── error_events.md └── README.md ├── repl ├── environment_variable_options.md ├── persistent_history.md ├── README.md ├── repl_features.md ├── class_REPLServer.md └── repl.md ├── readline ├── read_file_stream_line_by_line.md ├── README.md ├── tiny_cli.md └── class_Interface.md ├── string_decoder ├── class_StringDecoder.md └── README.md ├── crypto ├── README.md ├── notes.md ├── class_Certificate.md ├── class_Hash.md ├── class_Hmac.md ├── class_Verify.md ├── class_Sign.md ├── class_DiffieHellman.md ├── class_Cipher.md ├── class_Decipher.md └── class_ECDH.md ├── dgram ├── change_to_asynchronous_socketbind_behavior.md ├── a_note_about_udp_datagram_size.md ├── README.md └── dgram.md ├── book.json ├── stream ├── README.md └── simplified_constructor_api.md ├── README.md ├── synopsis └── README.md ├── dns ├── error_codes.md ├── implementation_considerations.md └── README.md ├── http ├── README.md ├── class_http_Agent.md ├── class_http_IncomingMessage.md └── http.md └── cluster ├── how_it_works.md └── README.md /GLOSSARY.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /nodejs-api-doc*.json 2 | /node_modules/ 3 | /_book/ 4 | -------------------------------------------------------------------------------- /url/README.md: -------------------------------------------------------------------------------- 1 | # URL(URL) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 该函数包含 URL 分解和解析工具。通过调用 `require('url')` 使用。 -------------------------------------------------------------------------------- /os/README.md: -------------------------------------------------------------------------------- 1 | # 系统(OS) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 提供了一些基本的与操作系统相关的实用参数。 6 | 7 | 通过 `require('os')` 使用该模块。 -------------------------------------------------------------------------------- /querystring/README.md: -------------------------------------------------------------------------------- 1 | # 查询字符串(Query Strings) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 该模块提供了一些处理查询字符串的实用程序。它提供以下方法: -------------------------------------------------------------------------------- /https/README.md: -------------------------------------------------------------------------------- 1 | # HTTPS(HTTPS) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | HTTPS 是使用 TLS/SSL 的 HTTP 协议。在 Node.js 中,它作为一个单独的模块来实现的。 -------------------------------------------------------------------------------- /v8/README.md: -------------------------------------------------------------------------------- 1 | # V8(V8) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 本模块暴露 Node.js 中内置的 V8 版本的具体事件和接口。这些接口都受到上游程序的影响,因此稳定性指标不在范围内。 6 | -------------------------------------------------------------------------------- /process/README.md: -------------------------------------------------------------------------------- 1 | # 进程(Process) 2 | 3 | `process` 对象是一个全局对象,可以在任何地方访问。它是一个 [EventEmitter](../events/class_EventEmitter.md#) 实例。 -------------------------------------------------------------------------------- /net/README.md: -------------------------------------------------------------------------------- 1 | # 网络(Net) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 该 `net` 模块提供了一个异步网络包装。它包含了用于创建服务器和客户端(被称为流)的功能。你可以通过 `require('net');` 包含此模块。 -------------------------------------------------------------------------------- /LOG.md: -------------------------------------------------------------------------------- 1 | #### v0.8 2016/11/25 2 | * 完成文档的初版翻译 3 | 4 | #### v0.5 2016/06/25 5 | * 调整项目结构,完成过半文档内容的翻译 6 | 7 | #### v0.1 2016/04/01 8 | * 完成目录的整理 -------------------------------------------------------------------------------- /cli/README.md: -------------------------------------------------------------------------------- 1 | # 命令行选项(Command Line Options) 2 | 3 | Node.js 附带了各种 CLI 选项。这些选项显示了内置调试,多种执行脚本的方式以及其他有用的运行时的选项。 4 | 5 | 要在终端中将此文档视为手册页,运行 `man node`。 -------------------------------------------------------------------------------- /path/README.md: -------------------------------------------------------------------------------- 1 | # 路径(Path) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 此模块包含用于处理和转换文件路径的工具。其中大多数方法只执行字符串转换。文件系统不会考虑去检查路径是否有效。 6 | 7 | 通过 `require('path')` 来使用该模块。 -------------------------------------------------------------------------------- /https/class_https_Agent.md: -------------------------------------------------------------------------------- 1 | # https.Agent类 2 | 3 | HTTPS 代理对象类似于 [http.Agent](../http/class_http_Agent.md#)。详见 [https.request()](./https.md#httpsrequestoptions-callback) 了解更多信息。 -------------------------------------------------------------------------------- /vm/README.md: -------------------------------------------------------------------------------- 1 | # 虚拟机(VM) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 你可以访问此模块: 6 | 7 | ``` javascript 8 | const vm = require('vm'); 9 | ``` 10 | 11 | JavaScript 代码可以被编译并立即运行或编译、保存并在以后运行。 -------------------------------------------------------------------------------- /appendix/README.md: -------------------------------------------------------------------------------- 1 | # 附录 2 | 3 | * [函数速查表](./functions_glossary.md) 4 | 5 | -------------------------------------------------- 6 | 7 | 附录包含着一些在原文档中未曾提供的篇章,这些篇章不属于原文档,但可能对部分有需求的用户会有很大的帮助。 -------------------------------------------------------------------------------- /modules/core_modules.md: -------------------------------------------------------------------------------- 1 | # 核心模块 2 | 3 | Node.js 中有些模块是编译成二进制的。这些模块在本文档的其他地方有更详细的描述。 4 | 5 | 核心模块定义在 Node.js 源代码的 `lib/` 目录下。 6 | 7 | `require()` 总是会优先加载核心模块。例如,`require('http')` 始终返回内置的 HTTP 模块,即使有同名文件。 -------------------------------------------------------------------------------- /debugger/watchers.md: -------------------------------------------------------------------------------- 1 | # 监视器 2 | 3 | 可以在调试时查看表达式和变量值。每个断点都会在当前上下文中评估观察列表中的每个表达式,并在列举断点的源代码前立即被显示。 4 | 5 | 通过键入 `watch('my_expression')` 来监视一个表达式, `watchers` 命令会将其打印在激活的监视器中。通过键入 `unwatch('my_expression')` 来移除一个监视器。 -------------------------------------------------------------------------------- /punycode/README.md: -------------------------------------------------------------------------------- 1 | # Punycode码(Punycode) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | [Punycode.js](https://mths.be/punycode) 自 Node.js v0.6.2+ 开始被内置,通过 `require('punycode')` 引入。(要在其它 Node.js 版本中使用它,请先使用 npm 安装 `punycode` 模块。) -------------------------------------------------------------------------------- /tls/alpn_npn_and_sni.md: -------------------------------------------------------------------------------- 1 | # ALPN、NPN和SNI 2 | 3 | ALPN(应用层协议协商拓展)、NPN(下一个协议协议协商)和 SNI(服务器名称表示)是 TLS 握手扩展: 4 | 5 | * ALPN/NPN - 允许多种协议使用一个 TLS 服务器(HTTP、SPDY、HTTP/2)。 6 | 7 | * SNI - 允许具有不同 SSL 证书的多个主机名使用一个 TLS 服务器。 -------------------------------------------------------------------------------- /timers/class_Immediate.md: -------------------------------------------------------------------------------- 1 | # Immediate 类 2 | 3 | 此对象在内部创建,并从 [setImmediate()](./scheduling_timers.md#setimmediatecallback-args) 返回。它可以传递给 [clearImmediate()](./cancelling_timers.md#clearimmediateimmediate) 以便取消计划的操作。 -------------------------------------------------------------------------------- /zlib/README.md: -------------------------------------------------------------------------------- 1 | # 压缩解压(ZLIB) 2 | 3 | 稳定度:2 - 稳定 4 | 5 | 你可以访问此模块: 6 | 7 | ```javascript 8 | const zlib = require('zlib'); 9 | ``` 10 | 11 | 这打包提供了 Gzip/Gunzip、 Deflate/Inflate 和 DeflateRaw/InflateRaw 类。每个类都采用相同的选项,并且是一个可读/可写流。 -------------------------------------------------------------------------------- /domain/domain.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [domain.create()](#create) 4 | 5 | -------------------------------------------------- 6 | 7 | 8 |
9 | ## domain.create() 10 | 11 | * 返回:{Domain} 12 | 13 | 返回一个新的 Domain 对象。 -------------------------------------------------------------------------------- /util/README.md: -------------------------------------------------------------------------------- 1 | # 实用工具(Utilities) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 这些函数都在 `'util'` 模块中。使用 `require('util')` 访问它们。 6 | 7 | `util` 模块主要用于支持 Node.js 内部 API 的需求。这其中的大部分工具对你自己的程序会非常有用。如果你发现在这些函数中缺少你需要的函数,不过,我们鼓励你编写自己的工具函数。我们对在 `util` 模块中增加不必要的 Node.js 的内部功能的任何需求都不感兴趣。 -------------------------------------------------------------------------------- /console/asynchronous_vs_synchronous_consoles.md: -------------------------------------------------------------------------------- 1 | # 异步与同步的控制台 2 | 3 | `console` 函数通常是异步的,除非目标对象是一个文件。带有高速磁盘的操作系统通常采用回写缓存;写入阻塞应该是一个非常罕见的情况,但它确实有可能发生。 4 | 5 | 此外,作为对 MAC OS X 中极小的(1kb)的缓存大小限制的一种解决方案,在 MAC OS X 上输出到 TTY(终端)时,控制台功能会遭到阻塞。这是为了防止 `stdout` 和 `stderr` 交叉在一起。 -------------------------------------------------------------------------------- /fs/buffer_api.md: -------------------------------------------------------------------------------- 1 | # Buffer API 2 | 3 | `fs` 函数支持传递和接收字符串和 Buffer 式的路径。后者的目的是使得可以在允许非 UTF-8 文件名的文件系统中工作。对于大多数典型用途,能在 Buffer 式的路径中工作是多余的,因为字符串 API 自动转换为 UTF-8 形式。 4 | 5 | *请注意*,在某些文件系统(如 NTFS 和 HFS+),文件名总是被编码为 UTF-8。在这些文件系统中,分配非 UTF-8 编码的 Buffers 到 `fs` 函数将无法像预期那样正常工作。 -------------------------------------------------------------------------------- /child_process/maxbuffer_and_unicode.md: -------------------------------------------------------------------------------- 1 | # maxBuffer 和 Unicode 2 | 3 | `maxBuffer` 选项是在 `stdout` 或 `stderr` 上用于指定允许的最大*八位字节*数,记住这一点非常重要 —— 如果超过这个值,子进程将会被终止。这尤其影响包含多字节字符编码的输出,如 UTF-8 或 UTF-16。例如,以下将输出 13 个 UTF-8 编码的八位字节到 stdout,尽管只有 4 个字符: 4 | 5 | ```javascript 6 | console.log('中文测试'); 7 | ``` -------------------------------------------------------------------------------- /errors/exceptions_vs_errors.md: -------------------------------------------------------------------------------- 1 | # 异常与错误 2 | 3 | JavaScript 异常通常是抛出一个无效操作的结果值或作为 `throw` 所表述的目标。虽然它不要求这些值是 `Error` 或继承自 `Error` 的类的实例,但会通过 Node.js 抛出所有异常或**将**成为 JavaScript 运行时的 `Error` 实例。 4 | 5 | 这些异常在 JavaScript 层是*无法恢复*的。这些异常总会引起 Node.js 进程的崩溃。这些例子包括 `assert()` 检测或在 C++ 层调用的 `abort()` 。 -------------------------------------------------------------------------------- /assert/README.md: -------------------------------------------------------------------------------- 1 | # 断言测试(Assertion Testing) 2 | 3 | > 稳定度:3 - 已锁定 4 | 5 | `assert` 模块提供一组简单的,可用于测试不变量断言测试。该模块是供 Node.js 内部使用的,但也可以通过 `require('assert')` 在应用代码中使用。然而,`assert` 不是一个测试框架,并且没有意愿成为通用的断言库。 6 | 7 | `assert` 模块的 API 已经[锁定](../documentation/stability_index.md#)。这意味着将不会增加或更改任何由模块实现和公开的方法。 -------------------------------------------------------------------------------- /cli/synopsis.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | `node [options] [v8 options] [script.js | -e "script"] [arguments]` 4 | 5 | `node debug [script.js | -e "script" | :] …` 6 | 7 | `node --v8-options` 8 | 9 | 执行无参数启动 [REPL](../repl/)。 10 | 11 | *关于 `node debug` 的更多信息,请参阅[调试器](../debugger/)文档。* -------------------------------------------------------------------------------- /errors/class_TypeError.md: -------------------------------------------------------------------------------- 1 | # TypeError类 2 | 3 | 是 `Error` 的一个子类用以表明所提供的参数不是一个被允许的类型。例如,将一个函数传递给一个需要字符串的参数时会产生一个 `TypeError` 。 4 | 5 | ```javascript 6 | require('url').parse(function () {}); 7 | // throws TypeError, since it expected a string 8 | ``` 9 | 10 | Node.js 会生成并以一种参数验证的形式**立即**抛出 `TypeError` 实例。 -------------------------------------------------------------------------------- /debugger/advanced_usage.md: -------------------------------------------------------------------------------- 1 | # 高级用法 2 | 3 | 启用和访问调试器的另一种方式是在启动 Node.js 时添加 `--debug` 命令行标志,或向已存在的 Node.js 进程发送 `SIGUSR1` 信号。 4 | 5 | 一个进程一旦以这种方式进入了调试模式,它就可以被 Node.js 调试器连接使用,通过连接已运行的进程的 `pid` 或访问这个正在监听的调试器的 URI: 6 | 7 | * `node debug -p ` - 通过 `pid` 连接进程 8 | 9 | * `node debug ` - 通过类似 localhost:5858 的 URI 连接进程 -------------------------------------------------------------------------------- /globals/README.md: -------------------------------------------------------------------------------- 1 | # 全局对象(Globals) 2 | 3 | * [方法和属性](./global.md) 4 | 5 | ---------------------------------------- 6 | 7 | 这些对象在所有模块中都是可用的。有些对象实际上并非在全局作用域内而是在模块作用域内——这种情况会在文档中特别指出。 8 | 9 | 此处列出的对象特定于 Node.js。有许多[内置对象](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects)是 JavaScript 语言本身的一部分,它们也可以全局访问。 -------------------------------------------------------------------------------- /documentation/json_output.md: -------------------------------------------------------------------------------- 1 | # JSON 格式输出 2 | 3 | > 稳定度:1 - 试验性 4 | 5 | 每个通过 markdown 生成的 HTML 文件都对应于一个具有相同数据结构的 JSON 文件。 6 | 7 | 该特性是在 Node.js v0.6.12 中引入的,目前仍是实验性功能。 8 | 9 | *目前本文档是基于 [Gitbook](https://www.gitbook.com) 生成的,如需查阅 `json` 格式的文档请转至[官方文档](https://nodejs.org/dist/latest-v5.x/docs/api/)查阅,[译者](https://github.com/Amery2010)注* -------------------------------------------------------------------------------- /domain/additions_to_error_objects.md: -------------------------------------------------------------------------------- 1 | # 特殊错误属性 2 | 3 | 任何时候一个 `Error` 对象通过了域(domain)路由,一些额外的字段会被添加到它上面。 4 | 5 | * `error.domain` 首先处理错误的域(domain)。 6 | 7 | * `error.domainEmitter` 触发了错误对象的 `'error'` 事件的事件触发器。 8 | 9 | * `error.domainBound` 绑定在域(domain)上的回调函数,并把错误作为第一个参数传过去。 10 | 11 | * `error.domainThrown` 一个布尔值,指示错误是否被抛出、触发或传递给绑定的回调函数。 -------------------------------------------------------------------------------- /domain/README.md: -------------------------------------------------------------------------------- 1 | # 域(Domain) 2 | 3 | > 稳定度:0 - 已废弃 4 | 5 | **该模块正准备废弃**。一旦替代的 API 已经敲定,该模块将被完全废弃。大多数最终用户不应该有理由使用这个模块。对于那些绝对必须要用到一个域(domain)所提供的功能的用户可以暂时依靠它,但应该在未来有不得不迁移到不同的解决方案的打算。 6 | 7 | 域(domain)提供了一种方法来处理多个不同的 IO 操作将其作为一个单独的组。如果有任何注册域(domain)的事件触发器或回调发出一个 `'error'` 事件,或抛出一个错误,那么域(domain)对象将会收到通知,而不是在 `process.on('uncaughtException')` 中处理丢失错误的情况,或导致程序伴随错误码立即退出。 -------------------------------------------------------------------------------- /buffer/buffers_and_es6_iteration.md: -------------------------------------------------------------------------------- 1 | # Buffers和ES6迭代器 2 | 3 | Buffers 可以通过 ECMAScript 2015 (ES6) 的 `for..of` 语法进行遍历。 4 | 5 | ```javascript 6 | const buf = Buffer(.from[1, 2, 3]); 7 | 8 | for (var b of buf) 9 | console.log(b) 10 | 11 | // Prints: 12 | // 1 13 | // 2 14 | // 3 15 | ``` 16 | 17 | 另外,`buf.values()` 、`buf.keys()` 和 `buf.entries()` 方法可用于创建迭代器。 -------------------------------------------------------------------------------- /tls/class_CryptoStream.md: -------------------------------------------------------------------------------- 1 | # CryptoStream类 2 | 3 | > 稳定度:0 - 已废弃:使用 [tls.TLSSocket](./class_tls_TLSSocket.md#) 替代。 4 | 5 | * [cryptoStream.bytesWritten](#cryptostreambyteswritten) 6 | 7 | -------------------------------------------------- 8 | 9 | 这是一个加密流。 10 | 11 | 12 | ## cryptoStream.bytesWritten 13 | 14 | 一个底层套接字的 bytesWritten 访问器代理,这会返回写入到套接字的总字节数,包括 TLS 开销。 -------------------------------------------------------------------------------- /modules/accessing_the_main_module.md: -------------------------------------------------------------------------------- 1 | # 访问主模块 2 | 3 | 当 Node.js 直接运行一个文件时,`require.main` 就被设置为它的 `module`。这意味着你可以直接在测试中确定文件是否已运行。 4 | 5 | ``` javascript 6 | require.main === module 7 | ``` 8 | 9 | 对于 `foo.js` 文件而言,通过 `node foo.js` 运行则为 `true`;通过 `require('./foo')` 运行则为 `false`。 10 | 11 | 因为 `module` 提供了一个 `filename` 属性(通常等于 `__filename`),所以可以通过 `require.main.filename` 来获取当前应用程序的入口点。 -------------------------------------------------------------------------------- /tls/class_SecurePair.md: -------------------------------------------------------------------------------- 1 | # SecurePair类 2 | 3 | * ['secure' 事件](#secure-事件) 4 | 5 | -------------------------------------------------- 6 | 7 | 通过 tls.createSecurePair 返回。 8 | 9 | 10 | ## 'secure' 事件 11 | 12 | 一旦该安全对已经成功建立安全的连接,这个事件会从 SecurePair 发出。 13 | 14 | 作为检测服务器端的 [secureConnection](./class_tls_Server.md#secureconnection-事件) 事件的手段,`pair.cleartext.authorized` 应检查并确认使用的证书是否被正确授权。 -------------------------------------------------------------------------------- /buffer/the_zero_fill_buffers_clo.md: -------------------------------------------------------------------------------- 1 | # --zero-fill-buffers命令行选项 2 | 3 | Node.js 可以在一开始就使用 `--zero-fill-buffers` 命令行选项强制所有新配置的 `Buffer` 和 `SlowBuffer` 实例,无论是通过 `new Buffer(size)` 还是 `new SlowBuffer(size)` ,都在创建时*自动用零填充*。使用这个标志*改变这些方法的默认行为*会对性能*有显著的影响*。建议只在有绝对必要新分配的 Buffer 实例不能包含潜在的敏感数据时才去执行 `--zero-fill-buffers` 选项。 4 | 5 | ``` 6 | $ node --zero-fill-buffers 7 | > Buffer(5); 8 | 9 | ``` -------------------------------------------------------------------------------- /addons/native_abstractions_for_nodejs.md: -------------------------------------------------------------------------------- 1 | # Node.js的原生抽象 2 | 3 | 文档中所示的每个例子都直接使用 Node.js 和 V8 API 实现插件。理解这一点很重要,V8 API 可以,并且已经在下一个(主要的) V8 发行版本中发生了巨大的变化。伴随着每一个变化,插件为了能够继续工作,可能需要进行更新和重新编译。Node.js 的发布计划是为了尽量减少这种变化的频率和影响,但有一点 Node.js 目前可以做到的是确保 V8 API 的稳定性。 4 | 5 | [Node.js的原生抽象](#)(或 `nan`)提供了一组推荐插件开发者使用的用以保持过去和未来的 V8 和 Node.js 版本之间的兼容性的工具。详见 `nan` [例子](https://github.com/nodejs/nan/tree/master/examples/) 了解它是如何使用的说明例证。 -------------------------------------------------------------------------------- /errors/class_SyntaxError.md: -------------------------------------------------------------------------------- 1 | # SyntaxError类 2 | 3 | 是 `Error` 的一个子类用于表示当前程序不是有效的 JavaScript 代码。这些错误只会产生和传播代码的评测结果。代码评测可能产生自 `eval`、`Function`、`require` 或 [vm](../vm/)。这些错误几乎都表示这是一个坏掉的程序。 4 | 5 | ```javascript 6 | try { 7 | require('vm').runInThisContext('binary ! isNotOk'); 8 | } catch (err) { 9 | // err will be a SyntaxError 10 | } 11 | ``` 12 | 13 | `SyntaxError` 实例在创建它们的上下文中是不可恢复的 - 它们只可能被其他上下文捕获。 -------------------------------------------------------------------------------- /tty/tty.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [tty.isatty(fd)](#ttyisattyfd) 4 | * [tty.setRawMode(mode)](#ttysetrawmodemode) 5 | 6 | -------------------------------------------------- 7 | 8 | ## tty.isatty(fd) 9 | 10 | 返回 `true` 或 `false` 取决于 `fd` 是否与终端相关联。 11 | 12 | 13 | ## tty.setRawMode(mode) 14 | 15 | > 稳定度:0 - 已废弃:使用 [tty.ReadStream#setRawMode](./class_ReadStream.md#rssetrawmodemode)(即 process.stdin.setRawMode)代替。 -------------------------------------------------------------------------------- /events/asynchronous_vs_synchronous.md: -------------------------------------------------------------------------------- 1 | # 异步和同步 2 | 3 | `EventListener` 会按照监听器的注册顺序同步地调用所有监听器。这对于确保事件的正确排序很重要以避免竞争条件或逻辑错误。在适当的时候,监听器函数也可以通过使用 `setImmediate()` 或 `process.nextTick()` 方法切换到异步操作模式: 4 | 5 | ``` javascript 6 | const myEmitter = new MyEmitter(); 7 | myEmitter.on('event', (a, b) => { 8 | setImmediate(() => { 9 | console.log('这是异步发生的'); 10 | }); 11 | }); 12 | myEmitter.emit('event', 'a', 'b'); 13 | ``` -------------------------------------------------------------------------------- /repl/environment_variable_options.md: -------------------------------------------------------------------------------- 1 | # 环境变量 2 | 3 | 内置 repl(通过运行 `node` 或 `node -i` 调用)可以通过以下环境变量进行控制: 4 | 5 | * `NODE_REPL_HISTORY` - 当给出有效路径时,持久性的 REPL 历史将被保存到指定的文件而不是在用户的主目录中的 `.node_repl_history`。设置这个变量为 `""` 将禁用持久性的 REPL 历史记录。它会从值中删除空格。 6 | 7 | * `NODE_REPL_HISTORY_SIZE` - 默认为 `1000`。如果历史可用,它用于控制保留多少行历史记录。必须为正数。 8 | 9 | * `NODE_REPL_MODE` - 可能是 `sloppy`、`strict` 或 `magic` 中的任何值。默认为 `magic`,它将在严格模式下自动运行“strict mode only”语句。 -------------------------------------------------------------------------------- /readline/read_file_stream_line_by_line.md: -------------------------------------------------------------------------------- 1 | # 示例:逐行读取文件流 2 | 3 | 一个常见的 `readline` 的 `input` 选项情况是将文件系统的可读流传递给它。这是一个如何处理文件逐行解析的例子: 4 | 5 | ``` javascript 6 | const readline = require('readline'); 7 | const fs = require('fs'); 8 | 9 | const rl = readline.createInterface({ 10 | input: fs.createReadStream('sample.txt') 11 | }); 12 | 13 | rl.on('line', (line) => { 14 | console.log('Line from file:', line); 15 | }); 16 | ``` -------------------------------------------------------------------------------- /string_decoder/class_StringDecoder.md: -------------------------------------------------------------------------------- 1 | # StringDecoder类 2 | 3 | * [decoder.write(buffer)](#write) 4 | * [decoder.end()](#end) 5 | 6 | -------------------------------------------------- 7 | 8 | 9 | 接受唯一一个参数 `encoding`,默认为 `'utf8'`。 10 | 11 | 12 |
13 | ## decoder.write(buffer) 14 | 15 | 返回一个解码后的字符串。 16 | 17 | 18 |
19 | ## decoder.end() 20 | 21 | 返回被留在缓冲区中的任何末尾字节。 -------------------------------------------------------------------------------- /repl/persistent_history.md: -------------------------------------------------------------------------------- 1 | # 永久历史 2 | 3 | 默认情况下,REPL 会保持 `node` REPL 会话之间的历史,通过保存到在用户的主目录中的 `.node_repl_history`。这可以通过设置环境变量 `NODE_REPL_HISTORY=""` 来禁用。 4 | 5 | ## NODE_REPL_HISTORY_FILE 6 | 7 | > 稳定度:0 - 已废弃:请改用 NODE_REPL_HISTORY。 8 | 9 | 在 Node.js/io.js v2.x 之前的版本中,REPL 历史是通过使用 `NODE_REPL_HISTORY_FILE` 环境变量来控制的,并且历史记录以 JSON 格式保存。此变量现已被废弃,并且你的 REPL 历史记录将自动转换为使用纯文本。新文件将保存到你的主目录,或由 `NODE_REPL_HISTORY` 变量定义的目录,如[此处](./environment_variable_options.md#)所述。 -------------------------------------------------------------------------------- /tty/README.md: -------------------------------------------------------------------------------- 1 | # 终端(TTY) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | `tty` 提供了 `tty.ReadStream` 和 `tty.WriteStream` 类。在大多数情况下,你不需要直接使用此模块。 6 | 7 | 当 Node.js 检测到它正在 TTY 上下文中运行时,那么 `process.stdin` 会是一个 `tty.ReadStream` 实例并且 `process.stdout` 会是一个 `tty.WriteStream` 实例。检查 Node.js 是否正在 TTY 上下文中运行的首选方法是去检测 `process.stdout.isTTY`: 8 | 9 | ``` bash 10 | $ node -p -e "Boolean(process.stdout.isTTY)" 11 | true 12 | $ node -p -e "Boolean(process.stdout.isTTY)" | cat 13 | false 14 | ``` -------------------------------------------------------------------------------- /errors/class_RangeError.md: -------------------------------------------------------------------------------- 1 | # RangeError类 2 | 3 | 是 `Error` 的一个子类用以表示一个给定参数没有被内部设置或函数值不在可接受范围内;无论这是一个数字范围还是给定函数参数的选项之外的设置(原文,whether that is a numeric range, or outside the set of options for a given function parameter。理解了半天也没搞明白这句话到底想说明什么...[译者](https://github.com/Amery2010)注)。 4 | 5 | 例如: 6 | 7 | ```javascript 8 | require('net').connect(-1); 9 | // throws RangeError, port should be > 0 && < 65536 10 | ``` 11 | 12 | Node.js 会生成并以一种参数验证的形式**立即**抛出 `RangeError` 实例。 -------------------------------------------------------------------------------- /modules/the_module_wrapper.md: -------------------------------------------------------------------------------- 1 | # 模块包装器 2 | 3 | 在执行模块代码之前,Node.js 会使用一个如下所示的函数包装器将其包装: 4 | 5 | ``` javascript 6 | (function (exports, require, module, __filename, __dirname) { 7 | // 你的模块代码实际上应该在这里 8 | }); 9 | ``` 10 | 11 | 通过这样做,Node.js 实现了以下几点: 12 | 13 | * 它保持顶级变量(用 `var`、`const` 或 `let` 定义)作用域是在模块内部而不是在全局对象上。 14 | 15 | * 它有助于提供一些实际上特定于模块的全局变量,例如: 16 | 17 | - 实现者可以用 `module` 和 `exports` 对象从模块中导出值。 18 | 19 | - 快捷变量 `__filename` 和 `__dirname` 包含了模块的文件名和目录的绝对路径。 -------------------------------------------------------------------------------- /buffer/buffer.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [buffer.INSPECT_MAX_BYTES](#INSPECT_MAX_BYTES) 4 | 5 | -------------------------------------------------- 6 | 7 | 8 |
9 | ## buffer.INSPECT_MAX_BYTES 10 | 11 | - {Number} 默认:50 12 | 13 | 在调用 `buffer.inspect()` 时返回最大字节数。这个数值可以被用户模块重写。查阅 [util.inspect()](../util/util.md#inspect)可以获得更多关于 `buffer.inspect()` 的行为细节。 14 | 15 | 注意,这个属性只存在于使用 `require('buffer')` 返回的 `buffer` 模块中,在全局的 Buffer 和 Buffer 实例中是不存在的。 -------------------------------------------------------------------------------- /tls/client_initiated_renegotiation_attack_mitigation.md: -------------------------------------------------------------------------------- 1 | # 缓解由客户端发起的重新协商攻击 2 | 3 | TLS 协议允许客户端重新协商 TLS 会话的某些方面。不幸的是,会话重新协商需要非等比的服务器端的资源,这使得它成为拒绝服务攻击的潜在媒介。 4 | 5 | 为了减轻这个的影响,重新协商被限制为每 10 分钟三次。当超过该阈值时,[tls.TLSSocket](./class_tls_TLSSocket.md#) 实例会发出一个错误。这些限制是可配置的: 6 | 7 | * `tls.CLIENT_RENEG_LIMIT`:重新协商次数限制,默认为 3。 8 | 9 | * `tls.CLIENT_RENEG_WINDOW`:重新协商窗口存活时间(以秒为单位),默认为 10 分钟。 10 | 11 | 不要在没有充分理解的情况下去修改这些默认参数。 12 | 13 | 测试服务器,使用 `openssl s_client -connect address:port` 连接并键入 `R`(即,小写的 `R` 后跟着回车键)几次。 -------------------------------------------------------------------------------- /zlib/class_options.md: -------------------------------------------------------------------------------- 1 | # 类参数 2 | 3 | 每个类需要一个 options 对象。所有选项都是可选的。 4 | 5 | 请注意有些选项仅对压缩有效,并会被解压缩类所忽略。 6 | 7 | * flush(默认:`zlib.Z_NO_FLUSH`) 8 | 9 | * finishFlush(默认:`zlib.Z_FINISH`) 10 | 11 | * chunkSize(默认:16*1024) 12 | 13 | * windowBits 14 | 15 | * level(仅用于压缩) 16 | 17 | * memLevel(仅用于压缩) 18 | 19 | * strategy(仅用于压缩) 20 | 21 | * dictionary(仅用于 deflate/inflate,缺省为空目录) 22 | 23 | `deflateInit2` 和 `inflateInit2` 的描述可以在 [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) 上查阅到更多内容。 -------------------------------------------------------------------------------- /fs/class_fs_ReadStream.md: -------------------------------------------------------------------------------- 1 | # fs.ReadStream类 2 | 3 | * ['open' 事件](#event_open) 4 | * [readStream.path](#path) 5 | 6 | -------------------------------------------------- 7 | 8 | 9 | `ReadStream` 是一个 [可读流](../stream/api_for_stream_consumers.md#class_Readable)。 10 | 11 |
12 | ## 'open' 事件 13 | 14 | * `fd` {Number} 给 ReadStream 使用整数文件描述符。 15 | 16 | 在打开 ReadStream 文件时触发。 17 | 18 | 19 |
20 | ## readStream.path 21 | 22 | 流读取的文件路径。 -------------------------------------------------------------------------------- /string_decoder/README.md: -------------------------------------------------------------------------------- 1 | # 字符串解码(String Decoder) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 通过 `require('string_decoder')` 使用该模块。这个模块将一个 buffer 解码成一个字符串。它是 `buffer.toString()` 的一个简单接口,但提供对 utf8 的支持。 6 | 7 | ```javascript 8 | const StringDecoder = require('string_decoder').StringDecoder; 9 | const decoder = new StringDecoder('utf8'); 10 | 11 | const cent = new Buffer([0xC2, 0xA2]); 12 | console.log(decoder.write(cent)); 13 | 14 | const euro = new Buffer([0xE2, 0x82, 0xAC]); 15 | console.log(decoder.write(euro)); 16 | ``` -------------------------------------------------------------------------------- /domain/implicit_binding.md: -------------------------------------------------------------------------------- 1 | # 隐式绑定 2 | 3 | 如果域(domain)正在使用中,那么所有**新建**的 `EventEmitter` 对象(包括 Stream 对象、请求、响应等)将在其创建时被隐式绑定到活动域。 4 | 5 | 此外,传递给低级事件循环的请求回调(如 fs.open 或其它 callback-taking 方法)会自动绑定到活动域。如果它们抛出,那么域会捕获该错误。 6 | 7 | 为了防止过多的内存使用情况,域对象本身不会隐性加入活动域中作为其子对象。如果是这样的话,那就很容易防止正常地垃圾回收请求和响应对象。 8 | 9 | 如果你*想*嵌套域对象作为父域的子域,那么你必须明确地添加它们。 10 | 11 | 隐性绑定后,路由会抛出错误和 `'error'` 事件到域(Domain)的 `'error'` 事件上,但不会在域(Domain)上注册 `EventEmitter`,因此 [domain.dispose()](./class_Domain.md#dispose) 不会关闭 `EventEmitter`。隐式绑定只关心抛出错误和 `'error'` 事件。 -------------------------------------------------------------------------------- /crypto/README.md: -------------------------------------------------------------------------------- 1 | # 加密(Crypto) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 该 `crypto` 模块提供了加密功能,包括一组用于包装 OpenSSL 的哈希,HMAC,加密,解密,签名和验证函数。 6 | 7 | 使用 `require('crypto')` 来访问这个模块。 8 | 9 | ``` javascript 10 | const crypto = require('crypto'); 11 | 12 | const secret = 'abcdefg'; 13 | const hash = crypto.createHmac('sha256', secret) 14 | .update('I love cupcakes') 15 | .digest('hex'); 16 | console.log(hash); 17 | // Prints: 18 | // c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e 19 | ``` -------------------------------------------------------------------------------- /tty/class_ReadStream.md: -------------------------------------------------------------------------------- 1 | # ReadStream类 2 | 3 | * [rs.isRaw](#rsisraw) 4 | * [rs.setRawMode(mode)](#rssetrawmodemode) 5 | 6 | -------------------------------------------------- 7 | 8 | 一个 `net.Socket` 子类,它表示 tty 的可读部分。在正常情况下,`process.stdin` 将是任何 Node.js 程序中唯一的 `tty.ReadStream` 实例(仅当 `isatty(0)` 为 true 时)。 9 | 10 | 11 | ## rs.isRaw 12 | 13 | 一个 `Boolean`,初始化为 `false`。它表示 `tty.ReadStream` 实例的当前“原始”状态。 14 | 15 | 16 | ## rs.setRawMode(mode) 17 | 18 | `mode` 应该是 `true` 或 `false`。这将设置 `tty.ReadStream` 的属性作为原始设备或默认值。`isRaw` 将被设置为结果模式。 -------------------------------------------------------------------------------- /documentation/stability_index.md: -------------------------------------------------------------------------------- 1 | # 稳定度 2 | 3 | 在整个文档中,你可能会看到某个部分的稳定性提示。Node.js 的 API 仍然会有一些小的变化,随着它的日益成熟,某些部分会比其他部分更可靠。有一部分接受过严格验证,被大量依赖的 API 几乎是不会改变的。也有一些是新增和实验性的,或已知具有危险性并在重新设计过程中的。 4 | 5 | 稳定性的指标如下: 6 | 7 | > 稳定度:0 - 已废弃 8 | 9 | 这是一个存在问题的特性,目前正计划修改。**请不要使用该特性**,使用此功能可能会导致警告,不要指望该特性能够向后兼容。 10 | 11 | > 稳定度:1 - 试验性 12 | 13 | 此功能可能会更改,我们会在命令行中进行提示。它可能会在将来版本中更改或删除。 14 | 15 | > 稳定度:2 - 稳定 16 | 17 | 该 API 已被证明是令人满意的。在 npm 中有着很高的使用率,我们在没有绝对的必要下不会对其修改。 18 | 19 | > 稳定度:3 - 已锁定 20 | 21 | 我们只接受对其进行的安全性、性能或修复 BUG 的建议。请不要在修改 API 方面给出提案,因为我们会拒绝这类建议。 -------------------------------------------------------------------------------- /modules/caching.md: -------------------------------------------------------------------------------- 1 | # 缓存 2 | 3 | 模块在第一次加载后会被缓存。这也意味着(类似其他缓存机制)如果每次调用 `require('foo')` 都解析到同一个文件,那么它将返回相同的对象。 4 | 5 | 多次调用 `require(foo)` 未必会导致模块中的代码执行多次。这是一个重要的特性。借助它, 可以返回“部分完成”的对象,从而允许传递依赖性加载, 即使它们可能导致循环。 6 | 7 | 如果你希望一个模块能够执行多次,那么,可以导出一个函数,然后多次调用该函数。 8 | 9 | 10 | ## 模块缓存的注意事项 11 | 12 | 模块是基于其解析的文件名进行缓存的。由于调用位置的不同,同一模块可能被解析成不同的文件名(比如从 `node_modules` 文件夹加载),如果它被解析成不同的文件时,就不能保证 `require('foo')` 总能返回完全相同的对象。 13 | 14 | 此外,在不区分大小写的文件系统或操作系统中,被解析成不同的文件名可以指向同一个文件,但缓存仍然会将它们视为不同的模块,并将重新加载该文件多次。例如:`require('./foo')` 和 `require('./FOO')` 返回两个不同的对象,而不会管 `./foo` 和 `./FOO` 是否是相同的文件。 -------------------------------------------------------------------------------- /timers/README.md: -------------------------------------------------------------------------------- 1 | # 定时器(Timers) 2 | 3 | * [预定定时器](./timers/scheduling_timers.md) 4 | * [取消定时器](./timers/cancelling_timers.md) 5 | * [Timeout 类](./timers/class_Timeout.md) 6 | * [Immediate 类](./timers/class_Immediate.md) 7 | 8 | -------------------------------------------------- 9 | 10 | > 稳定度:3 - 已锁定 11 | 12 | `timer` 模块暴露了一个全局的 API 用于调度在某个未来时间段内调用的函数。因为定时器函数是全局的,所以你没有必要调用 `require('timers')` 来使用该 API。 13 | 14 | Node.js 中的计时器函数实现了与 Web 浏览器提供的定时器类似的 API,但它使用了基于 [Node.js 事件循环](https://github.com/nodejs/node/blob/master/doc/topics/event-loop-timers-and-nexttick.md)构建的不同内部实现。 -------------------------------------------------------------------------------- /dgram/change_to_asynchronous_socketbind_behavior.md: -------------------------------------------------------------------------------- 1 | # socket.bind() 行为变为异步 2 | 3 | 截至 Node.js v0.10,[dgram.Socket#bind()](./class_dgram_Socket.md#socketbindoptions-callback) 更改为异步执行模式。遗留代码假定为同步行为,如以下示例所示: 4 | 5 | ``` javascript 6 | const s = dgram.createSocket('udp4'); 7 | s.bind(1234); 8 | s.addMembership('224.0.0.114'); 9 | ``` 10 | 11 | 必须改成传递一个回调函数到 [dgram.Socket#bind()](./class_dgram_Socket.md#socketbindoptions-callback) 函数: 12 | 13 | ``` javascript 14 | const s = dgram.createSocket('udp4'); 15 | s.bind(1234, () => { 16 | s.addMembership('224.0.0.114'); 17 | }); 18 | ``` -------------------------------------------------------------------------------- /tls/perfect_forward_secrecy.md: -------------------------------------------------------------------------------- 1 | # PFS(完全正向加密) 2 | 3 | 术语“正向加密”或“完全正向加密”描述密钥协议(即,密钥交换)方法的一个特点。实际上这意味着即使一台服务器的私有密钥被泄露,如果他们设法获得专门为每个会话生成的密钥对,通信只能由窃听者进行解密。 4 | 5 | 这是通过为每个握手密钥协定随机生成密钥对(与使用所有会话相同的密钥)来实现的。实现该技术的方法被叫做“ephemeral”,从而提供完全正向加密。 6 | 7 | 目前这两种方法常用于实现完全正向加密(注意字符“E”追加到传统的缩写): 8 | 9 | * [DHE](https://zh.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange):一个 ephemeral 版本的 Diffie Hellman 密钥协商协议。 10 | 11 | * [ECDHE](https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman):一个 ephemeral 版本的 Elliptic Curve Diffie Hellman 密钥协商协议。 12 | 13 | Ephemeral 方法可能有一些性能缺陷,因为密钥生成是昂贵的。 -------------------------------------------------------------------------------- /errors/class_ReferenceError.md: -------------------------------------------------------------------------------- 1 | # ReferenceError类 2 | 3 | 是 `Error` 的一个子类用以表示企图访问一个未定义的变量。这些错误通常表示代码中的错别字或一个坏掉的程序。虽然客户端代码可能会产生和传播这些错误,但在实践中,只有 V8 引擎会这么做。 4 | 5 | ```javascript 6 | doesNotExist; 7 | // throws ReferenceError, doesNotExist is not a variable in this program. 8 | ``` 9 | 10 | `ReferenceError` 实例会有一个 `error.arguments` 属性,其值为一个只有单个元素(一个代表变量未定义的字符串)的数组。 11 | 12 | ```javascript 13 | const assert = require('assert'); 14 | try { 15 | doesNotExist; 16 | } catch (err) { 17 | assert(err.arguments[0], 'doesNotExist'); 18 | } 19 | ``` 20 | 21 | 除非一个应用程序是动态生成并运行的代码,否则 `ReferenceError` 实例会始终被视为在代码或其依赖中的错误(bug)。 -------------------------------------------------------------------------------- /documentation/syscalls_and_man_pages.md: -------------------------------------------------------------------------------- 1 | # 系统调用和手册页 2 | 3 | 系统调用定义了用户程序和底层操作系统之间的接口,例如 [open(2)](http://man7.org/linux/man-pages/man2/open.2.html) 和 [read(2)](http://man7.org/linux/man-pages/man2/read.2.html) 。Node.js 的函数只是简单的包装了系统调用,就像文档中的 `fs.open()`。该文档链接到相应的手册页(以下简称手册页),其中描述了该系统调用的工作方式。 4 | 5 | **警告**:一些系统调用,例如 [lchown(2)](http://man7.org/linux/man-pages/man2/lchown.2.html) ,是特定于 BSD 系统。这就意味着 `fs.chown()` 只适用于 Mac OS X 和其他的 BSD 派生系统,在 Linux 上是不可用的。 6 | 7 | Windows 环境下的大多数系统回调和 Unix 环境下的等效,但有一些可能与 Linux 和 MAC OS X 不同。以一种微妙的关系为例,Windows 环境下有时不可能找到某些 Unix 系统回调的替代方案,详见 [Node issue 4760](https://github.com/nodejs/node/issues/4760) 。 -------------------------------------------------------------------------------- /https/class_https_Server.md: -------------------------------------------------------------------------------- 1 | # https.Server类 2 | 3 | * [server.timeout](#servertimeout) 4 | * [server.setTimeout(msecs, callback)](#serversettimeoutmsecs-callback) 5 | 6 | -------------------------------------------------- 7 | 8 | 9 | 这个类是 `tls.Server` 的子类,并且触发的事件和 [http.Server](../http/class_http_Server.md#) 相同。详见 [http.Server](../http/class_http_Server.md#) 了解更多信息。 10 | 11 | 12 | ## server.timeout 13 | 14 | 详见 [http.Server#timeout](../http/class_http_Server.md#servertimeout)。 15 | 16 | 17 | ## server.setTimeout(msecs, callback) 18 | 19 | 详见 [http.Server#setTimeout()](../http/class_http_Server.md#serversettimeoutmsecs-callback)。 -------------------------------------------------------------------------------- /modules/file_modules.md: -------------------------------------------------------------------------------- 1 | # 文件模块 2 | 3 | 如果按确切的文件名没有查找到该模块,那么 Node.js 会尝试添加 `.js` 和 `.json` 拓展名进行查找,如果还未找到,最后会尝试添加 `.node` 的拓展名进行查找。 4 | 5 | `.js` 文件会被解析为 JavaScript 文本文件,`.json` 文件会被解析为 JSON 文本文件。`.node` 文件会被解析为通过 `dlopen` 加载的编译后的插件模块。 6 | 7 | 请求的模块以 `'/'` 为前缀,则表示绝对路径。例如,`require('/home/marco/foo.js')` 将会加载的是 `/home/marco/foo.js` 文件。 8 | 9 | 请求的模块以 `'./'` 为前缀,则表示相对于调用 `require()` 的文件的路径。也就是说,`circle.js` 必须和 `foo.js` 在同一目录下以便于 `require('./circle')` 找到它。 10 | 11 | 当没有以 `'/'`、`'./'` 或 `'../'` 开头来表示文件时,这个模块必须是“核心模块”或加载自 `node_modules` 目录。 12 | 13 | 如果给定的路径不存在,`require()` 会抛出一个 `code` 属性为 `'MODULE_NOT_FOUND'` 的[错误](../errors/class_Error.md#)。 -------------------------------------------------------------------------------- /repl/README.md: -------------------------------------------------------------------------------- 1 | # 命令行交互(REPL) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | Read-Eval-Print-Loop(REPL)既可作为独立程序使用,也可轻松包含在其他程序中。REPL 提供了一种交互式运行 JavaScript 并查看结果的方法。它可以用于调试、测试或只是尝试新东西。 6 | 7 | 通过从命令行执行没有任何参数的 `node`,你将被放入 REPL。它有简单的 emacs 行编辑。 8 | 9 | ``` bash 10 | $ node 11 | Type '.help' for options. 12 | > a = [ 1, 2, 3]; 13 | [ 1, 2, 3 ] 14 | > a.forEach((v) => { 15 | ... console.log(v); 16 | ... }); 17 | 1 18 | 2 19 | 3 20 | ``` 21 | 22 | 对于高级线性编辑器,使用环境变量 `NODE_NO_READLINE=1` 启动 Node.js。在规范终端设置中启动主要的和调试的 REPL,这将允许你使用 `rlwrap`。 23 | 24 | 例如,你可以将其添加到你的 `bashrc` 文件中: 25 | 26 | ``` bash 27 | alias node="env NODE_NO_READLINE=1 rlwrap node" 28 | ``` -------------------------------------------------------------------------------- /readline/README.md: -------------------------------------------------------------------------------- 1 | # 逐行读取(Readline) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 通过 `require('readline')` 使用该模块。Readline 允许在逐行的基础上读取流(例如 [process.stdin](../process/process.md#stdin))。 6 | 7 | 请注意,一旦你调用此模块,直到你关闭界面前,你的 Node.js 程序将不会终止。以下代码是如何允许你的程序正常退出: 8 | 9 | ``` javascript 10 | const readline = require('readline'); 11 | 12 | const rl = readline.createInterface({ 13 | input: process.stdin, 14 | output: process.stdout 15 | }); 16 | 17 | rl.question('What do you think of Node.js? ', (answer) => { 18 | // TODO: Log the answer in a database 19 | console.log('Thank you for your valuable feedback:', answer); 20 | 21 | rl.close(); 22 | }); 23 | ``` -------------------------------------------------------------------------------- /dgram/a_note_about_udp_datagram_size.md: -------------------------------------------------------------------------------- 1 | # 有关 UDP 数据报大小的注意事项 2 | 3 | 一个 `IPv4/v6` 数据报的最大尺寸取决于 `MTU`(最大传输单位)和在 `Payload Length` 上的字段大小。 4 | 5 | * `Payload Length` 字段 `16 bits` 宽,这意味着正常的有效载荷超过 64K 八位字节,*包括*互联网报头和数据(65,507 字节 = 65,535 − 8 字节 UDP 头 − 20 字节 IP 头);这通常适用于环回接口,但是这样长的数据报消息对于大多数主机和网络是不切实际的。 6 | 7 | * `MTU` 是一个给定的链路层技术可以支持的最大数据报消息尺寸。对于任何链路,`IPv4` 规定最小的 `MTU` 限制是 `68` 个八位字节,同时推荐的 IPv4 `MTU` 是 `576`(通常推荐为拨号类型应用程序的 MTU),无论它们是整体还是碎片。 8 | 9 | 对于 IPv6,最小的 `MTU` 是 `1280` 个八位字节,然而,强制最小片段重组 buffer 大小为 `1500` 个八位字节。`68` 个八位字节的值非常小,由于大多数当前链路层技术,例如以太网,具有的最小 `MTU` 是 `1500`。 10 | 11 | 不可能提前知道包可能传输通过的每个链路的 `MTU`。发送大于接收方 `MTU` 的数据报将不起作用,因为包将被静默丢弃,而不会通知源,该数据未到达其预期接收者。 -------------------------------------------------------------------------------- /events/handling_events_only_once.md: -------------------------------------------------------------------------------- 1 | # 绑定一次性事件 2 | 3 | 当使用 `eventEmitter.on()` 方法注册监听器时,这个监听器会在*每次*发出该命名事件时被调用。 4 | 5 | ``` javascript 6 | const myEmitter = new MyEmitter(); 7 | let m = 0; 8 | myEmitter.on('event', () => { 9 | console.log(++m); 10 | }); 11 | myEmitter.emit('event'); 12 | // 打印:1 13 | myEmitter.emit('event'); 14 | // 打印:2 15 | ``` 16 | 17 | 当使用 `eventEmitter.once()` 方法时,可以注册对于特定事件最多调用一次的监听器。一旦触发了该事件,监听器就会被注销,随后调用该事件。 18 | 19 | ``` javascript 20 | const myEmitter = new MyEmitter(); 21 | let m = 0; 22 | myEmitter.once('event', () => { 23 | console.log(++m); 24 | }); 25 | myEmitter.emit('event'); 26 | // 打印:1 27 | myEmitter.emit('event'); 28 | // 忽略 29 | ``` -------------------------------------------------------------------------------- /fs/class_fs_WriteStream.md: -------------------------------------------------------------------------------- 1 | # fs.WriteStream类 2 | 3 | * ['open' 事件](#event_open) 4 | * [writeStream.path](#path) 5 | * [writeStream.bytesWritten](#bytesWritten) 6 | 7 | -------------------------------------------------- 8 | 9 | 10 | `WriteStream` 是一个 [可写流](../stream/api_for_stream_consumers.md#class_Writable)。 11 | 12 |
13 | ## 'open' 事件 14 | 15 | * `fd` {Number} 给 WriteStream 使用整数文件描述符。 16 | 17 | 在打开 WriteStream 文件时触发。 18 | 19 | 20 |
21 | ## writeStream.path 22 | 23 | 流写入的文件路径。 24 | 25 | 26 |
27 | ## writeStream.bytesWritten 28 | 29 | 迄今为止写入的字节数。不包括仍在排队等待写入的数据。 -------------------------------------------------------------------------------- /readline/tiny_cli.md: -------------------------------------------------------------------------------- 1 | # 示例:Tiny CLI 2 | 3 | 这里有一个如何使用所有这些接口一起来创建一个小型命令行界面的示例: 4 | 5 | ``` javascript 6 | const readline = require('readline'); 7 | const rl = readline.createInterface(process.stdin, process.stdout); 8 | 9 | rl.setPrompt('OHAI> '); 10 | rl.prompt(); 11 | 12 | rl.on('line', (line) => { 13 | switch (line.trim()) { 14 | case 'hello': 15 | console.log('world!'); 16 | break; 17 | default: 18 | console.log('Say what? I might have heard `' + line.trim() + '`'); 19 | break; 20 | } 21 | rl.prompt(); 22 | }).on('close', () => { 23 | console.log('Have a great day!'); 24 | process.exit(0); 25 | }); 26 | ``` -------------------------------------------------------------------------------- /dgram/README.md: -------------------------------------------------------------------------------- 1 | # 数据报处理(UDP/Datagram) 2 | 3 | 稳定度:2 - 稳定 4 | 5 | `dgram` 模块提供了对 UDP 数据报套接字的实现。 6 | 7 | ``` javascript 8 | const dgram = require('dgram'); 9 | const server = dgram.createSocket('udp4'); 10 | 11 | server.on('error', (err) => { 12 | console.log(`server error:\n${err.stack}`); 13 | server.close(); 14 | }); 15 | 16 | server.on('message', (msg, rinfo) => { 17 | console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`); 18 | }); 19 | 20 | server.on('listening', () => { 21 | var address = server.address(); 22 | console.log(`server listening ${address.address}:${address.port}`); 23 | }); 24 | 25 | server.bind(41234); 26 | // server listening 0.0.0.0:41234 27 | ``` -------------------------------------------------------------------------------- /fs/class_fs_FSWatcher.md: -------------------------------------------------------------------------------- 1 | # fs.FSWatcher类 2 | 3 | * ['change' 事件](#event_change) 4 | * ['error' 事件](#event_error) 5 | * [watcher.close()](#close) 6 | 7 | -------------------------------------------------- 8 | 9 | 10 | 从 `fs.watch()` 返回的对象是该类型。 11 | 12 | 13 |
14 | ## 'change' 事件 15 | 16 | * `event` {String} fs 的类型变化。 17 | 18 | * `filename` {String} 更改的文件名(如果相关/可用) 19 | 20 | 在监视的目录或文件更改了一些东西时触发。在 [fs.watch()](./fs.md#watch) 中了解更多内容。 21 | 22 | 23 |
24 | ## 'error' 事件 25 | 26 | * `error` {Error} 27 | 28 | 当发生错误时触发。 29 | 30 | 31 |
32 | ## watcher.close() 33 | 34 | 对给定的 `fs.FSWatcher` 停止监视变化。 -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "output": "./_book/", 3 | "generator": "site", 4 | "language": "zh", 5 | "plugins": [ 6 | "github", 7 | "sitemap" 8 | ], 9 | "pluginsConfig": { 10 | "github": { 11 | "url": "https://github.com/amery2010/nodejs-api-doc-cn/" 12 | }, 13 | "sitemap": { 14 | "hostname": "https://nodejs.xiangfa.org/" 15 | }, 16 | "sharing": { 17 | "facebook": false, 18 | "twitter": false, 19 | "google": false, 20 | "weibo": false, 21 | "instapaper": false, 22 | "vk": false, 23 | "all": ["weibo", "facebook", "twitter", "google"] 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /modules/loading_from_node_modules_folders.md: -------------------------------------------------------------------------------- 1 | # 从 `node_modules` 文件夹加载模块 2 | 3 | 如果传递给 `require()` 的模块标识符不是核心模块,也没有以 `'/'` 、 `'../'` 或 `'./'` 开头,那么 Node.js 会从当前模块的父目录开始,尝试在它的 `/node_modules` 文件夹里加载相应模块。Node.js 不会添加 `node_modules` 到已经以 `node_modules` 结尾的路径上。 4 | 5 | 如果没有找到,那么就再向上一级目录移动,直到文件系统的根目录为止。 6 | 7 | 例如,假设在 `'/home/ry/projects/foo.js'` 文件里调用了 `require('bar.js')` ,那么 Node.js 查找其位置的顺序依次为: 8 | 9 | * `/home/ry/projects/node_modules/bar.js` 10 | 11 | * `/home/ry/node_modules/bar.js` 12 | 13 | * `/home/node_modules/bar.js` 14 | 15 | * `/node_modules/bar.js` 16 | 17 | 这允许程序本地化它们的依赖,避免它们产生冲突。 18 | 19 | 通过在模块名称后包含路径后缀,你可以请求特定的文件或分布式的子模块。例如,`require('example-module/path/to/file')` 将被解析为相对于 `example-module` 所在位置的 `path/to/file`。后缀路径同样遵循模块路径的解析规则。 -------------------------------------------------------------------------------- /zlib/memory_usage_tuning.md: -------------------------------------------------------------------------------- 1 | # 优化内存占用 2 | 3 | Node.js 中的用法修改自 `zlib/zconf.h`: 4 | 5 | deflate 的内存需求(按字节): 6 | 7 | ``` 8 | (1 << (windowBits+2)) + (1 << (memLevel+9)) 9 | ``` 10 | 11 | 表示:128K 的 windowBits = 15 + 128K 的 memLevel = 8(默认值)加上几 KB 的小对象。 12 | 13 | 例如,如果你需要将默认内存需求从 256K 减少到 128K,设置选项: 14 | 15 | ``` 16 | { windowBits: 14, memLevel: 7 } 17 | ``` 18 | 19 | 当然,这通常会降低压缩等级(天下没有免费午餐)。 20 | 21 | inflate 的内存需求(按字节): 22 | 23 | ``` 24 | 1 << windowBits 25 | ``` 26 | 27 | 表示:32K 的 windowBits = 15(默认值)加上几 KB 的小对象。 28 | 29 | 这是除了内部输出的单个缓冲外的 `chunkSize` 大小,默认为 16K。 30 | 31 | zlib 的压缩速度主要受压缩级别 `level` 的影响。更高的压缩级别会有更好的压缩率,但也要花费更长时间。更低的压缩级别会有较低压缩率,但速度更快。 32 | 33 | 通常,使用更多内存的选项意味着 Node.js 能减少对 zlib 的调用,因为单次 `write` 操作能处理更多数据。因此,这是另一个影响速度和内存占用的因素。 -------------------------------------------------------------------------------- /modules/loading_from_the_global_folders.md: -------------------------------------------------------------------------------- 1 | # 从全局文件夹加载模块 2 | 3 | 如果 `NODE_PATH` 环境变量设置为一个以冒号分割的绝对路径列表。如果在其他位置找不到模块时,那么 Node.js 将会从这些路径中搜索。(注意:在 Windows 操作系统中,`NODE_PATH` 是以分号间隔的。) 4 | 5 | `NODE_PATH` 最初创建用以支持从不同路径加载模块,它不会在当前[模块解析](./all_together.md#)算法运行前被使用。 6 | 7 | 虽然目前仍然支持 `NODE_PATH` ,但在 Node.js 生态系统约定依赖模块的存放路径后已经很少用到了。有时,部署依赖 `NODE_PATH` 的模块,会在别人不知道必须设置 `NODE_PATH` 的情况下出现异常行为。有时,模块的依赖关系会发生变化,导致在搜索 `NODE_PATH` 时加载了不同的版本(甚至不同的模块)。 8 | 9 | 此外,Node.js 还会搜索以下路径: 10 | 11 | 1. `$HOME/.node_modules` 12 | 13 | 2. `$HOME/.node_libraries` 14 | 15 | 3. `$PREFIX/lib/node` 16 | 17 | 其中 `$HOME` 是用户的主目录,`$PREFIX` 是 Node.js 里配置的 `node_prefix`。 18 | 19 | 这些大多是由于历史原因产生的。**强烈建议你们将所有的依赖模块放在 `node_modules` 文件夹中**。它们将会更快、更可靠地被加载。 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /stream/README.md: -------------------------------------------------------------------------------- 1 | # 流(Stream) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 流是一个被 Node.js 中很多对象所实现的抽象接口。比如[对一个 HTTP 服务器的请求](../http/class_http_IncomingMessage.md#)是一个流,[process.stdout](../process/process.md#stdout) 也是一个流。流是可读、可写或兼具两者的。所有流都是 [EventEmitter](../events/class_EventEmitter.md#) 的实例。 6 | 7 | 您可以通过 `require('stream')` 加载 `Stream` 基类,这些基类提供了可读([Readable](./api_for_stream_consumers.md#class_Readable))流、可写([Writable](./api_for_stream_consumers.md#class_Writable))流、双工([Duplex](./api_for_stream_consumers.md#class_Duplex))流和转换([Transform](./api_for_stream_consumers.md#class_Transform))流。 8 | 9 | 本文档分为三个章节: 10 | 11 | 1. 第一章节介绍了,你在你的程序中使用流时,需要了解的那部分 API 。 12 | 13 | 2. 第二章节介绍了,当你自己实现一个流时,需要用到的那部分 API ,这些 API 是为了方便你这么做而设计的。 14 | 15 | 3. 第三章节深入讲解了流的工作方式,包括一些内部机制和函数,除非你明确知道你在做什么,否则尽量不要改动它们。 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Nodejs API 中文文档 2 | 3 | ### 前言 4 | 5 | 这份文档的翻译工作始于 2016年 4月初,由于翻译量较大,加之 Node.js 官方版本更新较快,因而目前尚无法跟上官网的(版本)更新节奏,因此不再进一步更新。 6 | 7 | 推荐大家阅读 [Node.js 中文网](http://nodejs.cn/api/) 维护的同步文档。 8 | 9 | ### 简介 10 | 11 | 这是一份 Node.js API 的中文文档,使用 [GitBook](https://github.com/GitbookIO/gitbook) 进行构建,适用于无力阅读英文原版的朋友参考阅读。 12 | 13 | ### 文档阅读 14 | 15 | [Gitbook 版(国内镜像)](https://nodejs.xiangfa.org) 16 | 17 | [Gitbook 版](https://amery2010.gitbooks.io/nodejs-api-doc-cn/) 18 | 19 | [GitHub 版](https://github.com/amery2010/nodejs-api-doc-cn/blob/master/SUMMARY.md) 20 | 21 | ### 许可协议 22 | 23 | **本文档采用 [知识共享署名-非商业性使用 3.0 未本地化版本许可协议](http://creativecommons.org/licenses/by-nc/3.0/deed.zh) 许可**。 24 | 25 | ### 备注 26 | 27 | 此文档的创建初衷是为了满足个人的学习需求,因此我目前已根据自己的对 Node.js 学习路线的思考对文档的章节顺序进行了适当的调整,此调整不影响正常的查阅。 28 | -------------------------------------------------------------------------------- /tty/class_WriteStream.md: -------------------------------------------------------------------------------- 1 | # WriteStream类 2 | 3 | * ['resize' 事件](#resize-事件) 4 | * [ws.columns](#wscolumns) 5 | * [ws.rows](#wsrows) 6 | 7 | -------------------------------------------------- 8 | 9 | 一个 `net.Socket` 子类,它表示 tty 的可写部分。在正常情况下,`process.stdout` 将是任何 Node.js 程序中唯一的 `tty.WriteStream` 实例(仅当 `isatty(1)` 为 true 时)。 10 | 11 | 12 | ## 'resize' 事件 13 | 14 | `function () {}` 15 | 16 | 当 `columns` 或 `rows` 属性中的任何一个已更改时,由 `refreshSize()` 发出。 17 | 18 | ``` javascript 19 | process.stdout.on('resize', () => { 20 | console.log('screen size has changed!'); 21 | console.log(`${process.stdout.columns}x${process.stdout.rows}`); 22 | }); 23 | ``` 24 | 25 | 26 | ## ws.columns 27 | 28 | 一个 `Number`,给出 TTY 当前具有的列数。此属性将更新 `'resize'` 事件。 29 | 30 | 31 | ## ws.rows 32 | 33 | 一个 `Number`,给出 TTY 当前具有的行数。此属性将更新 `'resize'` 事件。 -------------------------------------------------------------------------------- /events/passing_arguments_and_this_to_listeners.md: -------------------------------------------------------------------------------- 1 | # 给监听器传参 2 | 3 | `eventEmitter.emit()` 方法允许将任意参数传递给监听器函数。需要牢记的是,一个普通的监听器函数被 `EventEmitter` 调用时,标准的 `this` 关键词会被刻意得设置成指向附加到监听器上的这个 `EventEmitter` 实例的引用。 4 | 5 | ``` javascript 6 | const myEmitter = new MyEmitter(); 7 | myEmitter.on('event', function (a, b) { 8 | console.log(a, b, this); 9 | // 打印: 10 | // a b MyEmitter { 11 | // domain: null, 12 | // _events: { event: [Function] }, 13 | // _eventsCount: 1, 14 | // _maxListeners: undefined } 15 | }); 16 | myEmitter.emit('event', 'a', 'b'); 17 | ``` 18 | 19 | 也可以使用 ES6 的箭头函数作为监听器。然而,当你这么做时,`this` 关键词将不再引用 `EventEmitter` 实例。 20 | 21 | ``` javascript 22 | const myEmitter = new MyEmitter(); 23 | myEmitter.on('event', (a, b) => { 24 | console.log(a, b, this); 25 | // 打印:a b {} 26 | }); 27 | myEmitter.emit('event', 'a', 'b'); 28 | ``` -------------------------------------------------------------------------------- /cli/environment_variables.md: -------------------------------------------------------------------------------- 1 | # 环境变量 2 | 3 | * [NODE_DEBUG=module[,…]](#nodedebugmodule) 4 | * [NODE_PATH=path[:…]](#nodepathpath) 5 | * [NODE_DISABLE_COLORS=1](#nodedisablecolors1) 6 | * [NODE_ICU_DATA=file](#nodeicudatafile) 7 | * [NODE_REPL_HISTORY=file](#nodereplhistoryfile) 8 | 9 | -------------------------------------------------- 10 | 11 | 12 | ## NODE_DEBUG=module[,…] 13 | 14 | `','` - 分隔的应该打印调试信息的核心模块列表。 15 | 16 | 17 | ## NODE_PATH=path[:…] 18 | 19 | `':'` - 分隔的模块搜索路径的前缀列表。 20 | 21 | *请注意,在 Windows 中,是用 `';'` - 分隔的列表。* 22 | 23 | 24 | ## NODE_DISABLE_COLORS=1 25 | 26 | 当设置为 `1` 时,将不会在 REPL 中使用颜色。 27 | 28 | 29 | ## NODE_ICU_DATA=file 30 | 31 | ICU(Intl 对象)数据的数据路径。将在编译时使用 `small-icu` 支持的扩展链接的数据。 32 | 33 | 34 | ## NODE_REPL_HISTORY=file 35 | 36 | 用于存储持久性的 REPL 历史记录的文件的路径。它的默认路径是 `~/.node_repl_history`,该变量覆盖该值。将值设置为空字符串(`""` 或 `" "`)会禁用持久性的 REPL 历史记录。 -------------------------------------------------------------------------------- /modules/folders_as_modules.md: -------------------------------------------------------------------------------- 1 | # 将文件夹作为模块 2 | 3 | 可以把程序和库放到一个单独的文件夹里,并提供单一入口来指向它。有三种方式可以将文件夹传递给 `require()` 作为参数。 4 | 5 | 第一种方式是在文件夹的根目录下创建一个 `package.json` 的文件,它指定一个 `main` 模块。以下是一个 `package.json` 的文件示例: 6 | 7 | ``` javascript 8 | { 9 | "name": "some-library", 10 | "main": "./lib/some-library.js" 11 | } 12 | ``` 13 | 14 | 如果这是在 `./some-library` 文件夹中,那么 `require('./some-library')` 将尝试加载 `./some-library/lib/some-library.js`。 15 | 16 | 这就是 Node.js 处理 `package.json` 文件的方式。 17 | 18 | 注意:如果 `package.json` 中 `"main"` 条目指定的文件丢失,Node.js 将无法解析该模块,并抛出一个找不到该模块的默认错误: 19 | 20 | ``` javascript 21 | Error: Cannot find module 'some-library' 22 | ``` 23 | 24 | 如果目录里没有 `package.json` 这个文件,那么 Node.js 就会尝试去加载这个目录下的 `index.js` 或 `index.node` 文件。例如,如果上面例子中没有 `package.json`,那么 `require('./some-library')` 就将尝试加载以下文件: 25 | 26 | * `./some-library/index.js` 27 | 28 | * `./some-library/index.node` -------------------------------------------------------------------------------- /synopsis/README.md: -------------------------------------------------------------------------------- 1 | # 用法和示例 2 | 3 | `node [options] [v8 options] [script.js | -e "script"] [arguments]` 4 | 5 | 有关使用 Node.js 运行脚本的各种选项和方法的相关信息,请参阅文档中的[命令行选项](./cli/README.md)章节。 6 | 7 | 示例: 8 | 9 | 一个使用 Node.js 编写的输出 “Hello World” 的 [Web 服务器](../http/) 示例: 10 | 11 | ``` javascript 12 | const http = require('http'); 13 | 14 | const hostname = '127.0.0.1'; 15 | const port = 3000; 16 | 17 | const server = http.createServer((req, res) => { 18 | res.statusCode = 200; 19 | res.setHeader('Content-Type', 'text/plain'); 20 | res.end('Hello World\n'); 21 | }); 22 | 23 | server.listen(port, hostname, () => { 24 | console.log(`Server running at http://${hostname}:${port}/`); 25 | }); 26 | ``` 27 | 28 | 如果要运行这个服务器,需要先将代码保存名为 `example.js` 的文件,并使用 Node.js 来执行: 29 | 30 | ``` 31 | $ node example.js 32 | Server running at http://127.0.0.1:3000/ 33 | ``` 34 | 35 | 文档中的所有示例都可以使用相同的方式运行。 -------------------------------------------------------------------------------- /tls/modifying_the_default_tls_cipher_suite.md: -------------------------------------------------------------------------------- 1 | # 修改TLS的默认加密方式 2 | 3 | Node.js 建立了一套默认的启用和禁用 TLS 加密套件。当前,默认的加密套件是: 4 | 5 | ``` 6 | ECDHE-RSA-AES128-GCM-SHA256: 7 | ECDHE-ECDSA-AES128-GCM-SHA256: 8 | ECDHE-RSA-AES256-GCM-SHA384: 9 | ECDHE-ECDSA-AES256-GCM-SHA384: 10 | DHE-RSA-AES128-GCM-SHA256: 11 | ECDHE-RSA-AES128-SHA256: 12 | DHE-RSA-AES128-SHA256: 13 | ECDHE-RSA-AES256-SHA384: 14 | DHE-RSA-AES256-SHA384: 15 | ECDHE-RSA-AES256-SHA256: 16 | DHE-RSA-AES256-SHA256: 17 | HIGH: 18 | !aNULL: 19 | !eNULL: 20 | !EXPORT: 21 | !DES: 22 | !RC4: 23 | !MD5: 24 | !PSK: 25 | !SRP: 26 | !CAMELLIA 27 | ``` 28 | 29 | 默认值完全可以通过 `--tls-cipher-list` 命令行指令进行覆盖。例如,以下操作使得 `ECDHE-RSA-AES128-GCM-SHA256:!RC4` 成为默认 TLS 加密套件: 30 | 31 | ``` bash 32 | node --tls-cipher-list="ECDHE-RSA-AES128-GCM-SHA256:!RC4" 33 | ``` 34 | 35 | 请注意,包含在 Node.js 内的默认加密套件是经过精心挑选的,反映了当前的安全最佳实践并降低了风险。改变默认的加密套件会对一个应用程序的安全性产生显著影响。`--tls-cipher-list` 指令应该只有在有绝对必要的情况下使用。 -------------------------------------------------------------------------------- /tls/README.md: -------------------------------------------------------------------------------- 1 | # TLS/SSL(TLS/SSL) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 使用 `require('tls')` 访问这个模块。 6 | 7 | `tls` 模块使用 OpenSSL 提供传输层安全性和/或安全套接字层:加密流传输。 8 | 9 | TLS/SSL 是一个公开/私有密钥的底层结构。每个客户端和每个服务器必须有一个私钥。创建的私钥是这样的: 10 | 11 | ``` bash 12 | openssl genrsa -out ryans-key.pem 2048 13 | ``` 14 | 15 | 所有服务器和一些客户端需要有一个证书。证书是由证书颁发机构签署或自签名的公钥。第一步,获得证书是创建一个“证书签名请求”(CSR)文件。通过这样做: 16 | 17 | ``` bash 18 | openssl req -new -sha256 -key ryans-key.pem -out ryans-csr.pem 19 | ``` 20 | 21 | 要创建一个 CSR 自签名证书,可以这样做: 22 | 23 | ``` bash 24 | openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem 25 | ``` 26 | 27 | 另外,你可以发送 CSR 到证书颁发机构进行签名。 28 | 29 | 对于完全正向加密,需要生成 Diffie-Hellman 参数: 30 | 31 | ``` bash 32 | openssl pkcs12 -export -in agent5-cert.pem -inkey agent5-key.pem -certfile ca-cert.pem -out agent5.pfx 33 | ``` 34 | 35 | * `in`:证书 36 | 37 | * `inkey`:私钥 38 | 39 | * `certfile`:所有的 CA 证书串连在一个文件中,如 `cat ca1-cert.pem ca2-cert.pem > ca-cert.pem` -------------------------------------------------------------------------------- /dns/error_codes.md: -------------------------------------------------------------------------------- 1 | # 错误代码 2 | 3 | 每个 DNS 查询都可以返回下列之一的错误代码: 4 | 5 | * `dns.NODATA`:DNS 服务器返回没有数据的应答。 6 | 7 | * `dns.FORMERR`:DNS 服务器查询所要求的格式不正确。 8 | 9 | * `dns.SERVFAIL`:DNS 服务器返回一般故障。 10 | 11 | * `dns.NOTFOUND`:未找到域名。 12 | 13 | * `dns.NOTIMP`:DNS 服务器不执行请求的操作。 14 | 15 | * `dns.REFUSED`:DNS 服务器拒绝查询。 16 | 17 | * `dns.BADQUERY`:格式错误的 DNS 查询。 18 | 19 | * `dns.BADNAME`:格式错误的主机名。 20 | 21 | * `dns.BADFAMILY`:不支持的地址族。 22 | 23 | * `dns.BADRESP`:格式错误的 DNS 应答。 24 | 25 | * `dns.CONNREFUSED`:无法连接到 DNS 服务器。 26 | 27 | * `dns.TIMEOUT`:联系 DNS 服务器超时。 28 | 29 | * `dns.EOF`:文件结尾。 30 | 31 | * `dns.FILE`:读取文件错误。 32 | 33 | * `dns.NOMEM`:内存不足。 34 | 35 | * `dns.DESTRUCTION`:通道被销毁。 36 | 37 | * `dns.BADSTR`:格式错误的字符串。 38 | 39 | * `dns.BADFLAGS`:指定的非法标识。 40 | 41 | * `dns.NONAME`:主机名不是数字。 42 | 43 | * `dns.BADHINTS`:指定的非法提示标识。 44 | 45 | * `dns.NOTINITIALIZED`:还未初始化 c-ares 库。 46 | 47 | * `dns.LOADIPHLPAPI`:加载 iphlpapi.dll 失败。 48 | 49 | * `dns.ADDRGETNETWORKPARAMS`:无法找到获取网络参数的函数。 50 | 51 | * `dns.CANCELLED`:取消 DNS 查询。 -------------------------------------------------------------------------------- /events/error_events.md: -------------------------------------------------------------------------------- 1 | # 错误事件 2 | 3 | 当 `EventEmitter` 实例中发生错误时,典型的行为就是触发一个 `'error'` 事件。这些在 Node.js 中被视为特殊情况。 4 | 5 | 如果 `EventEmitter` 实例没有注册过至少一个监听器,当一个 `'error'` 事件触发时,将抛出这个错误,打印堆栈跟踪,并退出 Node.js 进程。 6 | 7 | ``` javascript 8 | const myEmitter = new MyEmitter(); 9 | myEmitter.emit('error', new Error('whoops!')); 10 | // Node.js 抛出错误,随后崩溃 11 | ``` 12 | 13 | 为了防止 Node.js 进程崩溃,可以在[进程对象 uncaughtException 事件](../process/process.md#event_uncaughtException)上注册监听器或使用[域(domain)](../domain/)模块(*请注意,`domain` 模块已被弃用*)。 14 | 15 | ``` javascript 16 | const myEmitter = new MyEmitter(); 17 | 18 | process.on('uncaughtException', (err) => { 19 | console.log('哇哦!这儿有个错误'); 20 | }); 21 | 22 | myEmitter.emit('error', new Error('whoops!')); 23 | // 打印:哇哦!这儿有个错误 24 | ``` 25 | 26 | 作为最佳实践,应该始终为 `'error'` 事件注册监听器: 27 | 28 | ``` javascript 29 | const myEmitter = new MyEmitter(); 30 | myEmitter.on('error', (err) => { 31 | console.log('哇哦!这儿有个错误'); 32 | }); 33 | myEmitter.emit('error', new Error('whoops!')); 34 | // 打印:哇哦!这儿有个错误 35 | ``` -------------------------------------------------------------------------------- /http/README.md: -------------------------------------------------------------------------------- 1 | # HTTP(HTTP) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 使用 HTTP 服务器和客户端必须 `require('http')`。 6 | 7 | 在 Node.js 中的 HTTP 接口被设计为支持使用该协议中与传统不同的许多功能。尤其是,大型的可能是块编码的消息。该接口谨慎或从不缓存整个请求或响应——用户能够以流形式传输数据。 8 | 9 | HTTP消息报头由一个像这样的对象表示: 10 | 11 | ``` javascript 12 | { 13 | 'content-length': '123', 14 | 'content-type': 'text/plain', 15 | 'connection': 'keep-alive', 16 | 'host': 'mysite.com', 17 | 'accept': '*/*' 18 | } 19 | ``` 20 | 21 | 键是小写,值没去修改。 22 | 23 | 为了支持全部可能的 HTTP 应用,Node.js 的 HTTP API 非常低级。它只涉及流处理和消息解析。它解析消息为头部和身体,但它并不解析实际的头部或身体。 24 | 25 | 请参阅 [message.headers](./class_http_IncomingMessage.md#messageheaders) 了解如何处理重复的头部。 26 | 27 | 收到的原始消息头被保留在 `rawHeaders` 属性中,它们是一个类似 `[key, value, key2, value2, ...]` 的数组。 28 | 29 | 例如,以前的消息头对象可能有类似以下的 `rawHeaders` 列表: 30 | 31 | ``` javascript 32 | [ 33 | 'ConTent-Length', '123456', 34 | 'content-LENGTH', '123', 35 | 'content-type', 'text/plain', 36 | 'CONNECTION', 'keep-alive', 37 | 'Host', 'mysite.com', 38 | 'accepT', '*/*' 39 | ] 40 | ``` -------------------------------------------------------------------------------- /buffer/buffers_and_character_encodings.md: -------------------------------------------------------------------------------- 1 | # Buffers和字符编码 2 | 3 | Buffers 通常用于代表编码的字符序列,比如 UTF8 、 UCS2 、 Base64 甚至 Hex-encoded 的数据。有可能通过使用一个明确的编码方法在 Buffers 和普通的 JavaScript 字符串对象之间进行相互转换。 4 | 5 | ```javascript 6 | const buf = Buffer.from('hello world', 'ascii'); 7 | console.log(buf.toString('hex')); 8 | // prints: 68656c6c6f20776f726c64 9 | console.log(buf.toString('base64')); 10 | // prints: aGVsbG8gd29ybGQ= 11 | ``` 12 | 13 | Node.js 目前支持的字符编码包括: 14 | 15 | * `'ascii'` - 仅支持 7位 ASCII 数据。如果设置去掉高位的话,这种编码方法是非常快的。 16 | 17 | * `'utf8'` - 多字节编码的Unicode字符。许多网页和其他文档格式使用 UTF-8 。 18 | 19 | * `'utf16le'` - 2或4个字节,小端编码的Unicode字符。支持代理对(U+10000 to U+10FFFF)。 20 | 21 | * `'ucs2'` - `'utf16le'` 的别名。 22 | 23 | * `'base64'` - Base64 字符串编码。当从一个字符串创建一个 buffer 时,按照 [RFC 4648, Section 5](https://tools.ietf.org/html/rfc4648#section-5) 里的规定,这种编码也将接受正确的“URL和文件名安全字母”。 24 | 25 | * `'binary'` - 一种把 buffer 编码成一字节(latin-1)编码字符串的方式。目前不支持 `'latin-1'` 字符串。通过 `'binary'` 来代替 `'latin-1'` 使用 `'latin-1'` 编码。 26 | 27 | * `'hex'` - 将每个字节编码为两个十六进制字符。 28 | 29 | -------------------------------------------------------------------------------- /documentation/README.md: -------------------------------------------------------------------------------- 1 | # 关于本文档 2 | 3 | * [稳定度](./stability_index.md) 4 | * [JSON 格式输出](./json_output.md) 5 | * [系统调用和手册页](./syscalls_and_man_pages.md) 6 | 7 | ------------------------------------------------------- 8 | 9 | 无论从参考还是从概念的角度来看,本文档的目的都是**全面解释 Node.js API**。文档的每个部分都会介绍一个内置的模块或更高层次的概念。 10 | 11 | 在某些情况下,属性类型,方法参数和提供给事件处理程序的参数在主题标题下的列表中有详细说明。 12 | 13 | 每个 `.html` 文档都有一个相应的 `.json` 文档,以结构化的方式呈现相同的信息。这个特性是实验性的,希望能够为一些需要对文档进行程序化操作的 IDE 或者其他工具提供帮助。 14 | 15 | 每个 `.html` 和 `.json` 文件都是基于源代码 `doc/api/` 目录下的 `.md` 文件生成的。本文档使用 `tools/doc/generate.js` 这个程序生成。`HTML` 模板位于 `doc/template.html`。 16 | 17 | *目前本文档是基于 [Gitbook](https://www.gitbook.com) 生成的,如需查阅 `json` 格式的文档请转至[官方文档](https://nodejs.org/dist/latest-v5.x/docs/api/)查阅,[译者](https://github.com/Amery2010)注* 18 | 19 | 如果你在阅读过程中发现文档中的错误,请[提交问题(issue)](https://github.com/nodejs/node/issues/new)或查阅[文档贡献指南](https://github.com/nodejs/node/blob/master/CONTRIBUTING.md)中关于如何提交问题的操作说明。 20 | 21 | *如果你在阅读过程发现翻译上的错误,请[提交问题(issue)](https://github.com/Amery2010/nodejs-api-doc-cn/issues/new)。* -------------------------------------------------------------------------------- /zlib/flushing.md: -------------------------------------------------------------------------------- 1 | # Flushing 2 | 3 | 在一个压缩流中调用 [.flush()](./zlib_class.md#flush) 会使得 zlib 尽可能多地返回当前的可能值。这可能会降低压缩质量的成本,但这在数据需要尽快使用时非常有用。 4 | 5 | 在以下的例子中,`flush()` 被用于在客户端写入一个部分压缩的 HTTP 响应: 6 | 7 | ```javascript 8 | const zlib = require('zlib'); 9 | const http = require('http'); 10 | 11 | http.createServer((request, response) => { 12 | // For the sake of simplicity, the Accept-Encoding checks are omitted. 13 | response.writeHead(200, { 14 | 'content-encoding': 'gzip' 15 | }); 16 | const output = zlib.createGzip(); 17 | output.pipe(response); 18 | 19 | setInterval(() => { 20 | output.write(`The current time is ${Date()}\n`, () => { 21 | // The data has been passed to zlib, but the compression algorithm may 22 | // have decided to buffer the data for more efficient compression. 23 | // Calling .flush() will make the data available as soon as the client 24 | // is ready to receive it. 25 | output.flush(); 26 | }); 27 | }, 1000); 28 | }).listen(1337); 29 | ``` -------------------------------------------------------------------------------- /cluster/how_it_works.md: -------------------------------------------------------------------------------- 1 | # 工作原理 2 | 3 | 工作进程是使用 [child_process.fork()](../child_process/asynchronous_process_creation.md#fork) 方法进行衍生的,以便它们可以通过 IPC 与父进程进行通信并通过服务器来处理来回。 4 | 5 | 集群模块支持两种分发传入连接的方法。 6 | 7 | 第一种(除 Windows 外,所有平台上的默认方法)为轮询式:主进程监听一个端口,接受新连接,并以轮询的方式分发给工作进程,并用一些内建机制来避免单个工作进程超载。 8 | 9 | 第二种方式是,主进程建立监听 socket,并将它发送给感兴趣的工作进程,由工作进程直接接受传入的连接。 10 | 11 | 第二种方式理论上性能最佳。然而在实践中,由于操作系统的调度变幻莫测,分发往往十分不平衡。负载曾被观测到超过 70% 的连接只结束了八个进程中的两个。 12 | 13 | 因为 `server.listen()` 将大部分工作交给了主进程,所以一个普通的 Node.js 进程和一个集群工作进程会在三种情况下有所区别: 14 | 15 | 1. `server.listen({fd: 7})` 由于消息被传递到主进程,**父进程**中的文件描述符 7 会被监听,并且句柄会被传递给工作进程,而不是监听工作进程中文件描述符 7 所引用的东西。 16 | 17 | 2. `server.listen(handle)` 明确地监听一个句柄会使得工作进程使用所给句柄,而不是与主进程通讯。如果工作进程已经拥有了该句柄,则假定你知道你在做什么。 18 | 19 | 3. `server.listen(0)` 通常,这会让服务器监听一个随机端口。然而,在集群中,各个工作进程每次 `listen(0)` 都会得到一样的“随机”端口。实际上,端口在第一次时是随机的,但在那之后却是可预知的。如果你想要监听一个唯一的端口,则请根据集群工作进程 ID 来生成端口号。 20 | 21 | 由于在 Node.js 或你的程序中并没有路由逻辑,工作进程之间也没有共享的状态,因此在你的程序中,诸如会话和登录等功能应当被设计成不能太过依赖于内存中的数据对象。 22 | 23 | 由于工作进程都是独立的进程,因此它们会根据你的程序的需要被终止或重新衍生,并且不会影响到其它工作进程。只要还有工作进程存在,服务器就会继续接受连接。但是,Node.js 不会自动为你管理工作进程的数量,根据你的程序所需管理工作进程池是你的责任。 -------------------------------------------------------------------------------- /addons/README.md: -------------------------------------------------------------------------------- 1 | # C/C++插件(C/C++ Addons) 2 | 3 | Node.js 插件是动态链接共享对象,用 C 或 C++ 编写,它可以使用 [require()](../globals/global.md#require) 函数加载到 Node.js 中,并且可以把它们当成普通的 Node.js 模块那样使用。它们主要用于提供 Node.js 和 C/C++ 库之间运行 JavaScript 的接口。 4 | 5 | 目前,用于实现插件的方法相当复杂,涉及多个组件和 API 的知识: 6 | 7 | * V8:Node.js 中目前用于提供 JavaScript 实现的 C++ 库。V8 提供了用于创建对象,调用函数等机制。V8 的 API 大部分记录在 `v8.h` 头文件(在 Node.js 的源代码树中的 `deps/v8/include/v8.h`)中,也可以在[网上](https://v8docs.nodesource.com/)找到。 8 | 9 | * [libuv](https://github.com/libuv/libuv):实现了 Node.js 事件循环、工作线程和和所有的平台的异步行为的 C 库。它也可作为一个跨平台的抽象库,使得在所有的主流操作系统中可以像 POSIX 那样访问许多常见的系统任务,如与文件系统、sockets、计时器和系统事件的交互变得容易。libuv 还提供了一个可被用于为更复杂的异步插件供能的类 pthreads 的抽象线程,这需要高于标准的事件循环。鼓励插件作者去思考如何通过 libuv 的无阻塞系统操作,工作线程或自定义使用 libuv 线程在 I/O 或其他时间密集型任务中降低工作负载来避免阻塞事件循环。 10 | 11 | * 内置的 Node.js 库。Node.js 自己导出我们可以使用的一些 C/C++ 的 API —— 其中最重要的是 `node::ObjectWrap` 类。 12 | 13 | * Node.js 包括一些其他的静态链接库,包括 OpenSSL。这些其他的库位于 Node.js 源代码树中的 `deps/` 目录。只有 V8 和 OpenSSL 标志(symbol)有目的地通过 Node.js 再导出,并且可以通过插件进行不同程度的使用。查阅[链接到 Node.js 自己的依赖](./hello_world.md#linking_to_nodejs_own_dependencies)了解附加信息。 14 | 15 | 本章节中的所有实例都可以[下载](https://github.com/nodejs/node-addon-examples),并可以作为你自己的插件的起始点。 -------------------------------------------------------------------------------- /cluster/README.md: -------------------------------------------------------------------------------- 1 | # 集群(Cluster) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | Node.js 的单个实例在单线程中运行。为了充分利用多核系统的用户有时想要启动 Node.js 进程的集群来处理负载。 6 | 7 | 集群模块可以使你轻松创建共享所有服务器端口的子进程。 8 | 9 | ``` javascript 10 | const cluster = require('cluster'); 11 | const http = require('http'); 12 | const numCPUs = require('os').cpus().length; 13 | 14 | if (cluster.isMaster) { 15 | // Fork workers. 16 | for (var i = 0; i < numCPUs; i++) { 17 | cluster.fork(); 18 | } 19 | 20 | cluster.on('exit', (worker, code, signal) => { 21 | console.log(`worker ${worker.process.pid} died`); 22 | }); 23 | } else { 24 | // Workers can share any TCP connection 25 | // In this case it is an HTTP server 26 | http.createServer((req, res) => { 27 | res.writeHead(200); 28 | res.end('hello world\n'); 29 | }).listen(8000); 30 | } 31 | ``` 32 | 33 | 运行 Node.js,现在所有的工作进程会共享 8000 端口: 34 | 35 | ``` bash 36 | $ NODE_DEBUG=cluster node server.js 37 | 23521,Master Worker 23524 online 38 | 23521,Master Worker 23526 online 39 | 23521,Master Worker 23523 online 40 | 23521,Master Worker 23528 online 41 | ``` 42 | 43 | 请注意,在 Windows 平台上,目前还不可以在一个工作进程中设置一个已命名的 pipe 服务器。 -------------------------------------------------------------------------------- /domain/explicit_binding.md: -------------------------------------------------------------------------------- 1 | # 显式绑定 2 | 3 | 有时,正在使用的域(domain)不是应该被用于一个特定的事件触发器的其中之一。或者,该事件触发器可能已在一个域的上下文中创建,但应该代替绑定到一些其他的域上。 4 | 5 | 例如,可能有一个正在被 HTTP 服务器使用的域,但也许我们想为每个请求使用一个单独的域。 6 | 7 | 这可以通过显式绑定实现。 8 | 9 | 例如: 10 | 11 | ```javascript 12 | // create a top-level domain for the server 13 | const domain = require('domain'); 14 | const http = require('http'); 15 | const serverDomain = domain.create(); 16 | 17 | serverDomain.run(() => { 18 | // server is created in the scope of serverDomain 19 | http.createServer((req, res) => { 20 | // req and res are also created in the scope of serverDomain 21 | // however, we'd prefer to have a separate domain for each request. 22 | // create it first thing, and add req and res to it. 23 | var reqd = domain.create(); 24 | reqd.add(req); 25 | reqd.add(res); 26 | reqd.on('error', (er) => { 27 | console.error('Error', er, req.url); 28 | try { 29 | res.writeHead(500); 30 | res.end('Error occurred, sorry.'); 31 | } catch (er) { 32 | console.error('Error sending 500', er, req.url); 33 | } 34 | }); 35 | }).listen(1337); 36 | }); 37 | ``` -------------------------------------------------------------------------------- /process/exit_codes.md: -------------------------------------------------------------------------------- 1 | # 退出码 2 | 3 | 当所有的异步操作都已经完成时,Node.js 会以 `0` 状态码正常退出。以下状态码在其他情况下使用: 4 | 5 | * `1` **未捕获的致命异常** - 这是一个未捕获的异常,并且它不是由域或一个 `'uncaughtException'` 事件处理器处理的。 6 | 7 | * `2` 未使用(由 Bash 保留用于固有的误用) 8 | 9 | * `3` **内置的 JavaScript 解析错误** - 内置的 JavaScript 源代码在 Node.js 的引导过程中导致了解析错误。这是极为罕见的,一般只会在 Node.js 的自身的发展过程中才会发生。 10 | 11 | * `4` **内置的 JavaScript 评估失败** - 内置的 JavaScript 源代码在 Node.js 的引导过程的评估失败时,返回一个函数值。这是极为罕见的,一般只会在 Node.js 的自身的发展过程中才会发生。 12 | 13 | * `5` **致命错误** - 在 V8 中有一个致命的不可恢复的错误。通常会在 stderr 中打印一条前缀为 `FATAL ERROR` 的错误。 14 | 15 | * `6` **非函数内部的异常处理程序** - 有一个未捕获的异常,但内部致命异常处理函数在某种程度上被设置为一个非函数,并且不能被调用。 16 | 17 | * `7` **内部异常处理程序运行时失败** - 有一个未捕获的异常,但在试图处理它内部的致命异常时,处理函数自身抛出一个错误。这是可能发生的,例如,如果一个 `process.on('uncaughtException')` 或 `domain.on('error')` 处理程序抛出一个错误。 18 | 19 | * `8` 未使用。在 Node.js 的早期版本中,退出码8,有时表示未捕获的异常。 20 | 21 | * `9` **无效参数** - 无论是指定了一个未知的选项,还是一个需要值的选项没有提供值。 22 | 23 | * `10` **内置的 JavaScript 运行时失败** - 当引导函数被调用时,内置的 JavaScript 源代码在 Node.js 的引导过程中抛出一个错误。这是极为罕见的,一般只会在 Node.js 的自身的发展过程中才会发生。 24 | 25 | * `12` **无效的调试参数** - 设置了 `--debug` 和/或 `--debug-brk` 选项,但选中了一个无效的端口号。 26 | 27 | * `>128` **信号退出** - 如果 Node.js 收到了像 `SIGKILL` 或 `SIGHUP` 这样的致命信号,那么它的退出码会是 `128` 以上的信号代码值。这是一个标准的 Unix 的做法,由于退出码被定义为 7位的整数,并将退出码设置为高阶位,然后包含所述信号代码的值。 -------------------------------------------------------------------------------- /modules/cycles.md: -------------------------------------------------------------------------------- 1 | # 循环 2 | 3 | 当循环调用 `require()` 时,模块可能在未完成执行时被返回。 4 | 5 | 考虑这样一种情况: 6 | 7 | `a.js`: 8 | 9 | ``` javascript 10 | console.log('a starting'); 11 | exports.done = false; 12 | const b = require('./b.js'); 13 | console.log('in a, b.done = %j', b.done); 14 | exports.done = true; 15 | console.log('a done'); 16 | ``` 17 | 18 | `b.js`: 19 | 20 | ``` javascript 21 | console.log('b starting'); 22 | exports.done = false; 23 | const a = require('./a.js'); 24 | console.log('in b, a.done = %j', a.done); 25 | exports.done = true; 26 | console.log('b done'); 27 | ``` 28 | 29 | `main.js`: 30 | 31 | ``` javascript 32 | console.log('main starting'); 33 | const a = require('./a.js'); 34 | const b = require('./b.js'); 35 | console.log('in main, a.done=%j, b.done=%j', a.done, b.done); 36 | ``` 37 | 38 | 当 `main.js` 加载 `a.js` 时,`a.js` 反向加载 `b.js`。那时,`b.js` 会尝试去加载 `a.js`。为了防止无限的循环,`a.js` 会返回一个 `exports` 对象的 **未完成副本** 给 `b.js` 模块。之后 `b.js` 完成加载,并将 `exports` 对象返回给 `a.js` 模块。 39 | 40 | 当 `main.js` 加载这两个模块时,它们都已经完成加载了。因此,该程序的输出将会是: 41 | 42 | ``` shell 43 | $ node main.js 44 | main starting 45 | a starting 46 | b starting 47 | in b, a.done = false 48 | b done 49 | in a, b.done = true 50 | a done 51 | in main, a.done=true, b.done=true 52 | ``` 53 | 54 | 如果你的程序里有循环的依赖模块,请确保它们按计划执行。 -------------------------------------------------------------------------------- /buffer/README.md: -------------------------------------------------------------------------------- 1 | # Buffer(Buffer) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 随着 ECMAScript 2015(ES6)推出了 `TypedArray` ,JavaScript 语言已经没有机制用于读取或操纵二进制数据流了。`Buffer` 类被采纳为 Node.js API 的一部分使得在 TCP 流和文件系统操作等的上下文中与八位字节流进行交互成为可能。 6 | 7 | 目前 `TypedArray` 已经被添加进 ES6 中,`Buffer` 类以一种更加优化和适用于 Node.js 用例的方式实现了 `Uint8Array` API。 8 | 9 | `Buffer` 类的实例类似于整数数组,但具有固定大小、分配 V8 外堆的原始内存的特点。`Buffer` 的大小在创建时被确定,且不能调整大小。 10 | 11 | `Buffer` 类在 Node.js 中是一个全局变量,因此不太可能像其他的模块那样永远需要使用 `require('buffer')`。 12 | 13 | ```javascript 14 | const buf1 = Buffer.alloc(10); 15 | // Creates a zero-filled Buffer of length 10. 16 | 17 | const buf2 = Buffer.alloc(10, 1); 18 | // Creates a Buffer of length 10, filled with 0x01. 19 | 20 | const buf3 = Buffer.allocUnsafe(10); 21 | // Creates an uninitialized buffer of length 10. 22 | // This is faster than calling Buffer.alloc() but the returned 23 | // Buffer instance might contain old data that needs to be 24 | // overwritten using either fill() or write(). 25 | 26 | const buf4 = Buffer.from([1, 2, 3]); 27 | // Creates a Buffer containing [01, 02, 03]. 28 | 29 | const buf5 = Buffer.from('test'); 30 | // Creates a Buffer containing ASCII bytes [74, 65, 73, 74]. 31 | 32 | const buf6 = Buffer.from('tést', 'utf8'); 33 | // Creates a Buffer containing UTF8 bytes [74, c3, a9, 73, 74]. 34 | ``` -------------------------------------------------------------------------------- /events/README.md: -------------------------------------------------------------------------------- 1 | # 事件(Events) 2 | 3 | * [EventEmitter 类](./class_EventEmitter.md) 4 | * [错误事件](./error_events.md) 5 | * [绑定一次性事件](./handling_events_only_once.md) 6 | * [将参数和 `this` 传递给监听器](./passing_arguments_and_this_to_listeners.md) 7 | * [异步和同步](./asynchronous_vs_synchronous.md) 8 | 9 | ------------------------------------------------------------ 10 | 11 | > 稳定度:2 - 稳定 12 | 13 | 大多数 Node.js 核心 API 都是采用惯用的异步事件驱动架构,其中某些类型的对象(称为“触发器”)周期性地发出命名事件来调用函数对象(“监听器”)。 14 | 15 | 例如:[net.Server](../net/class_net_Server.md) 对象会在每次有新连接时发出事件;[fs.readStream](../stream/api_for_stream_consumers.md#readStream) 对象会在文件被打开时发出事件;[stream](../stream/api_for_stream_consumers.md#stream) 对象在每当在数据可读时发出事件。 16 | 17 | 所有能发出事件的对象都是 `EventEmitter` 类的实例。这些对象公开了一个 `eventEmitter.on()` 函数,它允许将一个或多个函数附加到由该对象发出的命名事件上。通常情况下,事件名称是小写驼峰式 (camel-cased) 字符串,但也可以使用任何有效的 JavaScript 属性名。 18 | 19 | 每当 `EventEmitter` 发出事件,所有附加到特定事件上的函数都被*同步*调用。所有由监听器回调返回的值都会被*忽略*并被丢弃。 20 | 21 | 以下例子展示了一个只有单个监听器的简单的 `EventEmitter` 实例。`eventEmitter.on()` 用于注册监听器,`eventEmitter.emit()` 用于触发事件。 22 | 23 | ``` javascript 24 | const EventEmitter = require('events'); 25 | 26 | class MyEmitter extends EventEmitter {} 27 | 28 | const myEmitter = new MyEmitter(); 29 | myEmitter.on('event', () => { 30 | console.log('发生了一个事件!'); 31 | }); 32 | myEmitter.emit('event'); 33 | ``` -------------------------------------------------------------------------------- /dns/implementation_considerations.md: -------------------------------------------------------------------------------- 1 | # 实现中的注意事项 2 | 3 | 尽管 [dns.lookup()](./dns.md#lookup) 和每个 `dns.resolve*()/dns.reverse()` 函数都具有网络名称与网络地址相关联的同一个目标(或反之亦然),但是他们的行为却是完全不同的。这些差异可能对 Node.js 程序的行为产生微妙而显著的后果。 4 | 5 | 6 |
7 | ### dns.lookup() 8 | 9 | [dns.lookup()](./dns.md#lookup) 的原理与其他使用相同的操作系统设备的程序一样。例如,[dns.lookup()](./dns.md#lookup) 几乎总是像 `ping` 命令一样的方式解析给定的名称。在大多数类 POSIX 的操作系统中,[dns.lookup()](./dns.md#lookup) 函数的行为可以通过改变 `nsswitch.conf(5)` 和/或 `resolv.conf(5)` 的设置进行修改,但请注意,更改这些文件将改变*同一个操作系统上运行的所有其他程序*的行为。 10 | 11 | 尽管从 JavaScript 的角度来看,调用 `dns.lookup()` 会是异步,它通过同步调用运行在 libuv 线程池中的 `getaddrinfo(3)` 实现。由于 libuv 线程池的大小是固定的,这也意味着,如果出于某种原因 `getaddrinfo(3)` 的调用花费了很长时间,其他可能在 libuv 线程池(诸如文件系统操作)中运行的操作将经历性能下降。为了缓解这一问题,一个潜在的解决方案是通过将 'UV_THREADPOOL_SIZE' 环境变量设置为一个大于 4(当前的默认值)的值来增加 libuv 线程池的大小。有关 libuv 线程池的更多信息,请参阅 [libuv 的官方文档](http://docs.libuv.org/en/latest/threadpool.html)。 12 | 13 | 14 |
15 | ### dns.resolve(), dns.resolve*() and dns.reverse() 16 | 17 | 这些函数与 [dns.lookup()](./dns.md#lookup) 有着完全不同的实现。它们不使用 `getaddrinfo(3)` 并且它们总是执行网络上的 DNS 查询。该网络通信始终异步进行,并且不使用 libuv 线程池。 18 | 19 | 其结果是,这些函数不能与发生在(可以有 [dns.lookup()](./dns.md#lookup) 的) libuv 线程池中的其他处理具有相同的负面影响。 20 | 21 | 它们使用与 [dns.lookup()](./dns.md#lookup) 不同的配置文件。例如,他们不使用来自 `/etc/hosts` 的配置。 -------------------------------------------------------------------------------- /dns/README.md: -------------------------------------------------------------------------------- 1 | # 域名服务(DNS) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | `dns` 模块包含属于两个不同类别的函数: 6 | 7 | 1)函数使用底层的操作系统设备执行名称解析,并且不一定执行任何类型的网络通信。这个类别只包含一个函数: [dns.lookup()](./dns.md#lookup)。**开发者希望和同一操作系统中的其他应用程序的行为相同的方式执行名称解析应该使用 [dns.lookup()](./dns.md#lookup)**。 8 | 9 | 例如,监视 `nodejs.org`。 10 | 11 | ```javascript 12 | const dns = require('dns'); 13 | 14 | dns.lookup('nodejs.org', (err, addresses, family) => { 15 | console.log('addresses:', addresses); 16 | }); 17 | ``` 18 | 19 | 2)函数连接到实际的DNS服务器执行名称解析,并且*总是*使用网络来执行 DNS 查询。此类别包含 `dns` 模块里*除了* [dns.lookup()](./dns.md#lookup) 以外的所有函数。这些函数不使用与 [dns.lookup()](./dns.md#lookup) 相同的配置文件(如,`/etc/hosts`)。这些函数应该由不希望使用底层的操作系统设备执行名称解析的开发者使用,并且希望*始终*执行 DNS 查询。 20 | 21 | 下面是解析 `'nodejs.org'`,然后反向解析返回的 IP 地址的例子。 22 | 23 | ```javascript 24 | const dns = require('dns'); 25 | 26 | dns.resolve4('nodejs.org', (err, addresses) => { 27 | if (err) throw err; 28 | 29 | console.log(`addresses: ${JSON.stringify(addresses)}`); 30 | 31 | addresses.forEach((a) => { 32 | dns.reverse(a, (err, hostnames) => { 33 | if (err) { 34 | throw err; 35 | } 36 | console.log(`reverse for ${a}: ${JSON.stringify(hostnames)}`); 37 | }); 38 | }); 39 | }); 40 | ``` 41 | 42 | 一个在另一个之上进行选择会有微妙的后果,详情参阅[实施注意事项部分](./implementation_considerations.md#)获取更多信息。 -------------------------------------------------------------------------------- /timers/class_Timeout.md: -------------------------------------------------------------------------------- 1 | # Timeout 类 2 | 3 | * [timeout.unref()](#timeoutunref) 4 | * [timeout.ref()](#timeoutref) 5 | 6 | -------------------------------------------------- 7 | 8 | 此对象在内部创建,并从 [setTimeout()](./scheduling_timers.md#settimeoutcallback-delay-args) 和 [setInterval()](./scheduling_timers.md#setintervalcallback-delay-args) 返回。它可以分别传递给 [clearTimeout()](./cancelling_timers.md#cleartimeouttimeout) 或 [clearInterval()](./cancelling_timers.md#clearintervaltimeout) 以便取消计划的动作。 9 | 10 | 默认情况下,当使用 [setTimeout()](./scheduling_timers.md#settimeoutcallback-delay-args) 或 [setInterval()](./scheduling_timers.md#setintervalcallback-delay-args) 调度定时器时,只要定时器仍处于活动状态,Node.js 事件循环将继续运行。每个由这些函数返回的 `Timeout` 对象都可以导出可用于控制此默认行为的 `timeout.ref()` 和 `timeout.unref()` 函数。 11 | 12 | 13 | ## timeout.unref() 14 | 15 | 添加:v0.9.1 16 | 17 | 当被调用时,活动的 `Timeout` 对象将不需要 Node.js 事件循环保持活动。如果没有其他活动保持事件循环运行,那么该进程可以在 `Timeout` 对象的回调被调用之前退出。调用 `timeout.unref()` 多次将没有效果。 18 | 19 | *注意*:调用 `timeout.unref()` 创建一个内部定时器,将唤醒 Node.js 的事件循环。创建太多这类定时器可能会对 Node.js 应用程序的性能产生负面影响。 20 | 21 | 返回对 `Timeout` 的引用。 22 | 23 | 24 | ## timeout.ref() 25 | 26 | 添加:v0.9.1 27 | 28 | 调用时,只要 `Timeout` 处于活动状态就请求 Node.js *不要*退出事件循环。调用 `timeout.ref()` 多次将没有效果。 29 | 30 | *注意*:默认情况下,所有 `Timeout` 对象都处于 `'ref'd'` 状态,通常不需要调用 `timeout.ref()`,除非之前调用了 `timeout.unref()`。 31 | 32 | 返回对 `Timeout` 的引用。 -------------------------------------------------------------------------------- /url/url_parsing.md: -------------------------------------------------------------------------------- 1 | # URL解析 2 | 3 | * [转义字符](#转义字符) 4 | 5 | -------------------------------------------------- 6 | 7 | 解析的 URL 对象有下列部分或全部的字段,取决于它们是否存在于 URL 字符串中。不在 URL 字符串中的其他部分将不会出现在所解析的对象中。例子所展示的 URL: 8 | 9 | ``` 10 | `'http://user:pass@host.com:8080/p/a/t/h?query=string#hash'`。 11 | ``` 12 | 13 | * `href`:原始解析的完整 URL。无论是协议还是主机都是小写。 14 | 15 | 例子:`'http://user:pass@host.com:8080/p/a/t/h?query=string#hash'` 16 | 17 | * `protocol`:请求的协议,小写。 18 | 19 | 例子:`'http:'` 20 | 21 | * `slashes`:该协议要求冒号后斜线。 22 | 23 | 例子:`true` 或 `false` 24 | 25 | * `host`:全部小写的 URL 主机部分,包括端口信息。 26 | 27 | 例子:`'host.com:8080'` 28 | 29 | * `auth`:一个 URL 的认证信息部分。 30 | 31 | 例子:`'user:pass'` 32 | 33 | * `hostname`:只是主机中小写的主机名部分。 34 | 35 | 例子:`'host.com'` 36 | 37 | * `port`:主机的端口号部分。 38 | 39 | 例子:`'8080'` 40 | 41 | * `pathname`:URL 的路径部分,它处于主机之后,查询之前,包括初始的斜线,如果存在的话。不执行解码。 42 | 43 | 例子:`'/p/a/t/h'` 44 | 45 | * `search`:URL 的“查询字符串”部分,包括前导的 `?`。 46 | 47 | 例子:`'?query=string'` 48 | 49 | * `path`:`pathname` 和 `search` 级联。不执行解码。 50 | 51 | 例子:`'/p/a/t/h?query=string'` 52 | 53 | * `query`:'参数'查询字符串的一部分,或一个已解析的查询字符串对象。 54 | 55 | 例子:`'query=string'` 或 `{'query':'string'}` 56 | 57 | * `hash`:URL 的“片段”部分,包括前导的 `#`。 58 | 59 | 例子:`'#hash'` 60 | 61 | 62 | ## 转义字符 63 | 64 | 空格(`' '`)和以下字符会在 URL 对象的属性中被自动解析: 65 | 66 | ``` 67 | < > " ` \r \n \t { } | \ ^ ' 68 | ``` -------------------------------------------------------------------------------- /timers/cancelling_timers.md: -------------------------------------------------------------------------------- 1 | # 取消定时器 2 | 3 | * [clearTimeout(timeout)](#cleartimeouttimeout) 4 | * [clearInterval(timeout)](#clearintervaltimeout) 5 | * [clearImmediate(immediate)](#clearimmediateimmediate) 6 | 7 | -------------------------------------------------- 8 | 9 | 每个 [setTimeout()](./scheduling_timers.md#settimeoutcallback-delay-args)、[setInterval()](./scheduling_timers.md#setintervalcallback-delay-args) 和 [setImmediate()](./scheduling_timers.md#setimmediatecallback-args) 都会返回表示预定计时器的对象。这些可用于取消定时器并防止其触发。 10 | 11 | 12 | ## clearTimeout(timeout) 13 | 14 | 添加:v0.0.1 15 | 16 | * `timeout` {Timeout} 由 [setTimeout()](./scheduling_timers.md#settimeoutcallback-delay-args) 返回的 `Timeout` 对象。 17 | 18 | 取消由 [setTimeout()](./scheduling_timers.md#settimeoutcallback-delay-args) 创建的 `Timeout` 对象。 19 | 20 | 21 | ## clearInterval(timeout) 22 | 23 | 添加:v0.0.1 24 | 25 | * `timeout` {Timeout} 由 [setInterval()](./scheduling_timers.md#setintervalcallback-delay-args) 返回的 `Timeout` 对象。 26 | 27 | 取消由 [setInterval()](./scheduling_timers.md#setintervalcallback-delay-args) 创建的 `Timeout` 对象。 28 | 29 | 30 | ## clearImmediate(immediate) 31 | 32 | 添加:v0.9.1 33 | 34 | * `immediate` {Immediate} 由 [setImmediate()](./scheduling_timers.md#setimmediatecallback-args) 返回的 `Immediate` 对象。 35 | 36 | 取消由 [setImmediate()](./scheduling_timers.md#setimmediatecallback-args) 创建的 `Immediate` 对象。 -------------------------------------------------------------------------------- /modules/package_manager_tips.md: -------------------------------------------------------------------------------- 1 | # 附录:包管理器的技巧 2 | 3 | Node.js 的 `require()` 函数的语义被设计的足够通用化,可以支持支持许多合理的目录结构。包管理器程序(如 `dpkg`、`rpm` 和 `npm`)将有可能不用修改就能够从 Node.js 模块中构建本地包。 4 | 5 | 接下来我们将给你一个可行的目录结构建议: 6 | 7 | 假设我们想要在 `/usr/lib/node//` 目录中保存特定版本的包的内容。 8 | 9 | 包可以依赖于其他包。为了安装包 `foo`,可能需要安装指定版本的 `bar` 包。`bar` 包也可能具有依赖关系,并且在某些情况下依赖关系可能发生冲突或形成循环。 10 | 11 | 因为 Node.js 会查找它所加载的模块的真实路径(也就是说会解析符号链接),然后在 `node_modules` 目录中查询依赖关系,[如下所述](./loading_from_node_modules_folders.md),这种情况使用以下体系结构很容易解决: 12 | 13 | * `/usr/lib/node/foo/1.2.3/` - `foo` 1.2.3 版本的包内容 14 | 15 | * `/usr/lib/node/bar/4.3.2/` - `foo` 包所依赖的 `bar` 的包内容 16 | 17 | * `/usr/lib/node/foo/1.2.3/node_modules/bar` - 指向 `/usr/lib/node/bar/4.3.2/` 的符号链接 18 | 19 | * `/usr/lib/node/bar/4.3.2/node_modules/*` - 指向 `bar` 包所依赖的包的符号链接 20 | 21 | 因此,即便存在循环依赖或依赖冲突,每个模块还是可以获得它所依赖的包的一个可用版本。 22 | 23 | 当 `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` 指向的版本。 24 | 25 | 此外,为了进一步优化模块搜索过程,不要将包直接放在 `/usr/lib/node` 目录中,而是将它们放在 `/usr/lib/node_modules//` 目录中。 这样在找不到依赖包的情况下,Node.js 就不会在 `/usr/node_modules` 或 `/node_modules` 目录中查找了。 26 | 27 | 为了使模块在 Node.js 的 REPL 中可用,你可能需要将 `/usr/lib/node_modules` 目录加入到 `$NODE_PATH` 28 | 环境变量中。由于在 `node_modules` 目录中搜索模块使用的是相对路径,使得调用 `require()` 获得的是基于真实路径的文件,因此包本身可以放在任何位置。 -------------------------------------------------------------------------------- /zlib/constants.md: -------------------------------------------------------------------------------- 1 | # 常量 2 | 3 | 所有定义在 zlib.h 上的常量也同样定义在 `require('zlib')`。在正常的操作过程中,你几乎不会用到这些。编入文档只是为了让你对它们的存在不会感到意外。该章节几乎完全来自 [zlib 的文档](http://zlib.net/manual.html#Constants)。详见 [http://zlib.net/manual.html#Constants](http://zlib.net/manual.html#Constants)。 4 | 5 | 允许的 flush 值。 6 | 7 | * `zlib.Z_NO_FLUSH` 8 | 9 | * `zlib.Z_PARTIAL_FLUSH` 10 | 11 | * `zlib.Z_SYNC_FLUSH` 12 | 13 | * `zlib.Z_FULL_FLUSH` 14 | 15 | * `zlib.Z_FINISH` 16 | 17 | * `zlib.Z_BLOCK` 18 | 19 | * `zlib.Z_TREES` 20 | 21 | 压缩/解压缩函数的返回值。负数代表错误,正数代表特殊但正常的事件。 22 | 23 | * `zlib.Z_OK` 24 | 25 | * `zlib.Z_STREAM_END` 26 | 27 | * `zlib.Z_NEED_DICT` 28 | 29 | * `zlib.Z_ERRNO` 30 | 31 | * `zlib.Z_STREAM_ERROR` 32 | 33 | * `zlib.Z_DATA_ERROR` 34 | 35 | * `zlib.Z_MEM_ERROR` 36 | 37 | * `zlib.Z_BUF_ERROR` 38 | 39 | * `zlib.Z_VERSION_ERROR` 40 | 41 | 压缩级别。 42 | 43 | * `zlib.Z_NO_COMPRESSION` 44 | 45 | * `zlib.Z_BEST_SPEED` 46 | 47 | * `zlib.Z_BEST_COMPRESSION` 48 | 49 | * `zlib.Z_DEFAULT_COMPRESSION` 50 | 51 | 压缩策略。 52 | 53 | * `zlib.Z_FILTERED` 54 | 55 | * `zlib.Z_HUFFMAN_ONLY` 56 | 57 | * `zlib.Z_RLE` 58 | 59 | * `zlib.Z_FIXED` 60 | 61 | * `zlib.Z_DEFAULT_STRATEGY` 62 | 63 | data_type 字段的可能值。 64 | 65 | * `zlib.Z_BINARY` 66 | 67 | * `zlib.Z_TEXT` 68 | 69 | * `zlib.Z_ASCII` 70 | 71 | * `zlib.Z_UNKNOWN` 72 | 73 | deflate 压缩方法(该版本仅支持一种)。 74 | 75 | * `zlib.Z_DEFLATED` 76 | 77 | 初始化 zalloc / zfree / opaque。 78 | 79 | * `zlib.Z_NULL` -------------------------------------------------------------------------------- /process/signal_events.md: -------------------------------------------------------------------------------- 1 | # 信号事件 2 | 3 | 当进程接收到信号时触发。标准的 POSIX 信号名称(如,`SIGINT`、 `SIGHUP` 等)列表详见([sigaction(2)](http://man7.org/linux/man-pages/man2/sigaction.2.html))。 4 | 5 | 监听 `SIGINT` 的例子: 6 | 7 | ```javascript 8 | // Start reading from stdin so we don't exit. 9 | process.stdin.resume(); 10 | 11 | process.on('SIGINT', () => { 12 | console.log('Got SIGINT. Press Control-D to exit.'); 13 | }); 14 | ``` 15 | 16 | 发送 `SIGINT` 信号最简单的方式是在大多数终端程序中使用 `Control-C`。 17 | 18 | 注意: 19 | 20 | `SIGUSR1` 由 Node.js 保留,用以开启调试器。它也可以设置一个监听器但不会中断调试器的启动。 21 | 22 | `SIGTERM` 和 `SIGINT` 是非 Windows 平台上在以代码 `128 + signal number` 退出前重置终端模式的默认处理信号。如果监听到其中一个信号被设置,它默认的行为都会被移除(Node.js 将不复存在)。 23 | 24 | `SIGPIPE` 默认被忽略。它可以设置监听器。 25 | 26 | `SIGHUP` 在 Windows 上,是在控制台窗口关闭时产生,在其他平台上也是在各种类似的条件下产生(详见,[signal(7)](http://man7.org/linux/man-pages/man7/signal.7.html))。它可以设置监听器,然而 Node.js 约10秒后会被 Windows 无条件终止。在非 Windows 平台上,`SIGHUP` 的默认行为是终止 Node.js ,但一旦设置了监听器,它的默认行为会被移除。 27 | 28 | `SIGTERM` 在 Windows 是不被支持,它可以被监听的。 29 | 30 | `SIGINT` 在所有平台的终端上都支持,并且通常是由 `CTRL+C`(虽然这也许配置的)产生的。当启用了终端原始模式时,它不再产生。 31 | 32 | `SIGBREAK` 在 Windows 平台上,当按下 `CTRL+BREAK` 时发出,在非 Windows 平台上,它是可以被设置的,但没有办法发送或生成它。 33 | 34 | `SIGWINCH` 在控制台已经调整后发出。在 Windows 中,当光标被移动时,或者当一个可读的 tty 在原始模式下使用时,这仅会在写入到控制台时发生。 35 | 36 | `SIGKILL` 不能设置监听器,它在所有平台上的 Node.js 中会无条件终止。 37 | 38 | `SIGSTOP` 不能设置监听器。 39 | 40 | 请注意,Windows 不支持发送信号,但 Node.js 提供了一些仿真方法 `process.kill()` 和 `child_process.kill()` 。发送信号 `0` 可用于测试一个进程是否存在。发送 `SIGINT`、 `SIGTERM` 和 `SIGKILL` 会导致目标进程无条件终止。 -------------------------------------------------------------------------------- /buffer/class_SlowBuffer.md: -------------------------------------------------------------------------------- 1 | # SlowBuffer类 2 | 3 | * [new SlowBuffer(size)](#new_SlowBuffer) 4 | 5 | -------------------------------------------------- 6 | 7 | 8 | 返回一个不被池管理的 Buffer 。 9 | 10 | 为了避免创建大量独立分配的 Buffer 带来的垃圾回收开销,默认情况下小于 4KB 的空间都是切割自一个较大的独立对象。这种策略既提高了性能也改善了内存使用,因为 V8 不需要跟踪和清理很多 `Persistent` 对象。 11 | 12 | 当开发者需要将池中一小块数据保留不确定的一段时间,较为妥当的办法是用 `SlowBuffer` 创建一个不被池管理的 Buffer 实例并将相应数据拷贝出来。 13 | 14 | ```javascript 15 | // need to keep around a few small chunks of memory 16 | const store = []; 17 | 18 | socket.on('readable', () => { 19 | var data = socket.read(); 20 | // allocate for retained data 21 | var sb = SlowBuffer(10); 22 | // copy the data into the new allocation 23 | data.copy(sb, 0, 0, 10); 24 | store.push(sb); 25 | }); 26 | ``` 27 | 28 | `SlowBuffer` 应该仅作为开发者已经观察到他们的应用保留了过度的内存时的最后手段。 29 | 30 | 31 |
32 | ## new SlowBuffer(size) 33 | 34 | - `size` {Number} 35 | 36 | 分配一个 `size` 字节大小的新 `SlowBuffer`。`size` 必须小于等于 `require('buffer').kMaxLength`(在64位架构上 `kMaxLength` 的大小是 `(2^31)-1`)的值,否则将抛出一个 [RangeError](../errors/class_RangeError.md#) 的错误。如果 `size` 小于 0 将创建一个特定的 0 长度(zero-length )的 SlowBuffer。 37 | 38 | `SlowBuffer` 实例的底层内存是*没被初始化过*的。新创建的 `SlowBuffer` 的内容是*未知*的,并*可能包含敏感数据*。通过使用 `buf.fill(0)` 将一个 `SlowBuffer` 初始化为零。 39 | 40 | ```javascript 41 | const SlowBuffer = require('buffer').SlowBuffer; 42 | const buf = new SlowBuffer(5); 43 | console.log(buf); 44 | // 45 | // (octets will be different, every time) 46 | buf.fill(0); 47 | console.log(buf); 48 | // 49 | ``` -------------------------------------------------------------------------------- /modules/all_together.md: -------------------------------------------------------------------------------- 1 | # 总的来说... 2 | 3 | 想要获取调用 `require()` 时加载的确切的文件名,请使用 `require.resolve()` 函数。 4 | 5 | 综上所述,以下用伪代码的形式来表述 require.resolve 中的高级算法是如何工作的: 6 | 7 | ``` 8 | require(X) from module at path Y 9 | 1. If X is a core module, 10 | a. return the core module 11 | b. STOP 12 | 2. If X begins with './' or '/' or '../' 13 | a. LOAD_AS_FILE(Y + X) 14 | b. LOAD_AS_DIRECTORY(Y + X) 15 | 3. LOAD_NODE_MODULES(X, dirname(Y)) 16 | 4. THROW "not found" 17 | 18 | LOAD_AS_FILE(X) 19 | 1. If X is a file, load X as JavaScript text. STOP 20 | 2. If X.js is a file, load X.js as JavaScript text. STOP 21 | 3. If X.json is a file, parse X.json to a JavaScript Object. STOP 22 | 4. If X.node is a file, load X.node as binary addon. STOP 23 | 24 | LOAD_AS_DIRECTORY(X) 25 | 1. If X/package.json is a file, 26 | a. Parse X/package.json, and look for "main" field. 27 | b. let M = X + (json main field) 28 | c. LOAD_AS_FILE(M) 29 | 2. If X/index.js is a file, load X/index.js as JavaScript text. STOP 30 | 3. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP 31 | 4. If X/index.node is a file, load X/index.node as binary addon. STOP 32 | 33 | LOAD_NODE_MODULES(X, START) 34 | 1. let DIRS=NODE_MODULES_PATHS(START) 35 | 2. for each DIR in DIRS: 36 | a. LOAD_AS_FILE(DIR/X) 37 | b. LOAD_AS_DIRECTORY(DIR/X) 38 | 39 | NODE_MODULES_PATHS(START) 40 | 1. let PARTS = path split(START) 41 | 2. let I = count of PARTS - 1 42 | 3. let DIRS = [] 43 | 4. while I >= 0, 44 | a. if PARTS[I] = "node_modules" CONTINUE 45 | b. DIR = path join(PARTS[0 .. I] + "node_modules") 46 | c. DIRS = DIRS + DIR 47 | d. let I = I - 1 48 | 5. return DIRS 49 | ``` -------------------------------------------------------------------------------- /console/README.md: -------------------------------------------------------------------------------- 1 | # 控制台(Console) 2 | 3 | * [Console 类](./class_Console.md) 4 | * [异步与同步的控制台](./asynchronous_vs_synchronous_consoles.md) 5 | 6 | ---------------------------------------- 7 | 8 | 9 | > 稳定度:2 - 稳定 10 | 11 | `console` 模块提供了一个简单的调试控制台,与 Web 浏览器提供的 JavaScript 控制台机制类似。 12 | 13 | 该模块导出两个特定组件: 14 | 15 | * 一个 `Console` 类,包含类似于 `console.log()` 、 `console.error()` 和 `console.warn()` 这些方法,可以用于写入任何的 Node.js 流。 16 | 17 | * 一个全局的 `console` 实例,用于写入 `stdout` 和 `stderr`。由于该对象是一个全局变量,它可以在没有调用 `require('console')` 的情况下使用。 18 | 19 | 使用全局 `console` 的示例: 20 | 21 | ``` javascript 22 | console.log('hello world'); 23 | // 在 stdout 中打印: hello world 24 | console.log('hello %s', 'world'); 25 | // 在 stdout 中打印: hello world 26 | console.error(new Error('Whoops, something bad happened')); 27 | // 在 stderr 中打印: [Error: Whoops, something bad happened] 28 | 29 | const name = 'Will Robinson'; 30 | console.warn(`Danger ${name}! Danger!`); 31 | // 在 stderr 中打印: Danger Will Robinson! Danger! 32 | ``` 33 | 34 | 使用 `Console` 类的示例: 35 | 36 | ``` javascript 37 | const out = getStreamSomehow(); 38 | const err = getStreamSomehow(); 39 | const myConsole = new console.Console(out, err); 40 | 41 | myConsole.log('hello world'); 42 | // 在 stdout 中打印: hello world 43 | myConsole.log('hello %s', 'world'); 44 | // 在 stdout 中打印: hello world 45 | myConsole.error(new Error('Whoops, something bad happened')); 46 | // 在 stderr 中打印: [Error: Whoops, something bad happened] 47 | 48 | const name = 'Will Robinson'; 49 | myConsole.warn(`Danger ${name}! Danger!`); 50 | // 在 stderr 中打印: Danger Will Robinson! Danger! 51 | ``` 52 | 53 | 虽然 `Console` 类的 API 是根据浏览器的 `console` 对象设计的,但 Node.js 中的 `Console` 并没有完全复制浏览器中的功能。 -------------------------------------------------------------------------------- /crypto/notes.md: -------------------------------------------------------------------------------- 1 | # 注意 2 | 3 | * [旧的流 API(Node.js v0.10 之前的版本)](#旧的流-apinodejsv010-之前的版本) 4 | * [近期 ECDH 的变化](#近期-ECDH-的变化) 5 | * [对弱的或泄密的算法的支持](#对弱的或泄密的算法的支持) 6 | 7 | -------------------------------------------------- 8 | 9 | 10 | ## 旧的流 API(Node.js v0.10 之前的版本) 11 | 12 | 在存在统一的 Stream API 的概念之前,Crypto 模块已添加到 Node.js 中,并在之前用 [Buffer](../buffer/) 对象处理二进制数据。因此,许多 `crypto` 定义的类有通常在其他由 [streams]() API 实现的 Node.js 类(如,`update()`、`final()` 或 `digest()`)中找不到的方法。此外,许多方法接受和返回 `'binary'` 编码的字符串,而不是 [Buffer](../buffer/)。这个默认值在 Node.js v0.8 之后改为默认使用 [Buffer](../buffer/) 对象。 13 | 14 | 15 | ## 近期 ECDH 的变化 16 | 17 | 非动态生成的密钥对的 ECDH 的用法已被简化。如今,[ecdh.setPrivateKey()](./class_ECDH.md#ecdhsetprivatekeyprivatekey-encoding) 可以使用预选的私钥来调用,并且相关联的公共点(密钥)将被计算并存储在对象中。这允许代码仅存储和提供 EC 密钥对的私有部分。[ecdh.setPrivateKey()](./class_ECDH.md#ecdhsetprivatekeyprivatekey-encoding) 现在还可以验证私钥对所选曲线的有效性。 18 | 19 | [ecdh.setPublicKey()](./class_ECDH.md#ecdhsetpublickeypublickey-encoding) 方法现在已被废弃,因为把它包含在 API 中的并没有什么用处。应该设置先前存储的私钥,或者调用 [ecdh.generateKeys()](./class_ECDH.md#ecdhgeneratekeysencoding-format)。使用[ecdh.setPublicKey()](./class_ECDH.md#ecdhsetpublickeypublickey-encoding) 的主要缺点是它可能会使得 ECDH 密钥对处于不一致的状态。 20 | 21 | 22 | ## 对弱的或泄密的算法的支持 23 | 24 | `crypto` 模块仍然支持一些已经泄密和目前不推荐使用的算法。API 还允许使用具有较小密钥大小的密码和散列,这些密钥和散列被认为太弱而无法安全使用。 25 | 26 | 用户应根据其安全要求,对选择的加密算法和密钥大小负全责。 27 | 28 | 基于 [NIST SP 800-131A](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf) 的建议: 29 | 30 | * MD5 和 SHA-1 在需要抗冲突性的场合(例如,数字签名)时将不可接受。 31 | 32 | * 用于 RSA、DSA 和 DH 算法的密钥建议至少 2048 位,并且 ECDSA 和 ECDH 的曲线至少为 224 位,这样的话,在几年内可以安全使用。 33 | 34 | * `modp1`、`modp2` 和 `modp5` 的 DH 组的密钥大小小于 2048 位,不推荐使用。 35 | 36 | 有关其他建议和详细信息,请详见[参考](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf)。 -------------------------------------------------------------------------------- /child_process/README.md: -------------------------------------------------------------------------------- 1 | # 子进程(Child Processes) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 子进程模块提供了衍生子进程的能力,这个能力和 [popen(3)](http://linux.die.net/man/3/popen) 方式上类似,但不完全相同。这种能力主要由 `child_process.spawn()` 函数提供: 6 | 7 | ```javascript 8 | const spawn = require('child_process').spawn; 9 | const ls = spawn('ls', ['-lh', '/usr']); 10 | 11 | ls.stdout.on('data', (data) => { 12 | console.log(`stdout: ${data}`); 13 | }); 14 | 15 | ls.stderr.on('data', (data) => { 16 | console.log(`stderr: ${data}`); 17 | }); 18 | 19 | ls.on('close', (code) => { 20 | console.log(`child process exited with code ${code}`); 21 | }); 22 | ``` 23 | 24 | 默认情况下,在 Node.js 的父进程和衍生的子进程之间会建立 `stdin`、`stdout` 和 `stderr` 的管道。这也使得数据流可以以无阻塞的方式通过这些管道。*但是请注意,有些程序内部使用行缓冲(line-buffered)I/O。虽然这并不影响 Node.js,它可能意味着发送到子过程数据可能无法立即消费。* 25 | 26 | `child_process.spawn()` 方法异步衍生子进程,不会阻塞 Node.js 的事件循环。`child_process.spawnSync()` 函数以同步的方式提供了同样的功能,它会阻塞事件循环,直到衍生的子进程退出或终止。 27 | 28 | 为了方便起见,`child_process` 模块提供了少有的同步和异步的替代品 [child_process.spawn()](./synchronous_process_creation.md#spawn) 和 [child_process.spawnSync()](./asynchronous_process_creation.md#spawnSync) 。*请注意,这些替代品是在 `child_process.spawn()` 或 `child_process.spawnSync()` 的基础上实现的。* 29 | 30 | * `child_process.exec()`:衍生一个 shell 并在 shell 内部运行一个命令,当完成时,会向回调函数传递 `stdout` 和 `stderr`。 31 | 32 | * `child_process.execFile()`:和 `child_process.exec()` 类似,除了它直接衍生命令,而不需要先衍生一个 shell。 33 | 34 | * `child_process.fork()`:衍生一个新的 Node.js 进程,并且通过建立一个允许父进程和子进程之间相互发送信息的 IPC 通讯通道来调用指定的模块。 35 | 36 | * `child_process.execSync()`:`child_process.exec()` 的一个同步版本,这*会*阻塞 Node.js 的事件循环。 37 | 38 | * `child_process.execFileSync()`:`child_process.execFile()` 的一个同步版本,这*会*阻塞 Node.js 的事件循环。 39 | 40 | 对于某些使用情况,如自动化 shell 脚本,[同步版本](./synchronous_process_creation.md#)可能更方便。在多数情况下,同步的方法会显著地影响性能,因为它拖延了事件循环直到衍生进程完成。 -------------------------------------------------------------------------------- /repl/repl_features.md: -------------------------------------------------------------------------------- 1 | # REPL新特性 2 | 3 | 在 REPL 内,Control+D 将退出。可以输入多行表达式。全局变量和局部变量都支持使用 Tab 补全。核心模块将按需加载到环境中。例如,访问 `fs` 将 `require()` 该 `fs` 模块作为 `global.fs`。 4 | 5 | 特殊变量 `_`(下划线)包含最后一个表达式的结果。 6 | 7 | ``` bash 8 | > [ 'a', 'b', 'c' ] 9 | [ 'a', 'b', 'c' ] 10 | > _.length 11 | 3 12 | > _ += 1 13 | 4 14 | ``` 15 | 16 | REPL 提供了对全局作用域中任何变量的访问权限。你可以通过将其分配给与每个 `REPLServer` 关联的 `context` 对象来显式地将一个变量公开给 REPL。例如: 17 | 18 | ``` javascript 19 | // repl_test.js 20 | const repl = require('repl'); 21 | var msg = 'message'; 22 | 23 | repl.start('> ').context.m = msg; 24 | ``` 25 | 26 | `context` 对象中的变量在 REPL 中显示为本地变量: 27 | 28 | ``` bash 29 | $ node repl_test.js 30 | > m 31 | 'message' 32 | ``` 33 | 34 | 有一些特殊的 REPL 命令: 35 | 36 | * `.break` - 在输入多行表达式时,有时你会迷失或只是不在乎完成它。`.break` 会重来。 37 | 38 | * `.clear` - 重置 `context` 对象为一个空对象,并清除任何的多行表达式。 39 | 40 | * `.exit` - 关闭 `I/O` 流,这将导致 REPL 退出。 41 | 42 | * `.help` - 显示这些特殊的命令列表。 43 | 44 | * `.save` - 将当前的 REPL 会话保存到文件中。 `.save ./file/to/save.js` 45 | 46 | * `.load` - 将文件加载到当前的 REPL 会话中。 `.load ./file/to/load.js` 47 | 48 | REPL 中的以下组合键具有以下特殊效果: 49 | 50 | * `C` - 类似于 `.break` 关键字。终止当前命令。在空白行上按两次可强制退出。 51 | 52 | * `D` - 类似于 `.exit` 关键字。 53 | 54 | * `` - 显示全局和局部(作用域)的变量。 55 | 56 | 57 | ## 显示在 REPL 中的自定义对象 58 | 59 | 当打印值时,REPL 模块在内部使用 [util.inspect()](../util/util.md#inspect)。然而,`util.inspect` 将调用委托给对象的 `inspect()` 函数,如果它有的话。你可以在[这里](../util/util.md#custom_inspect_function_on_Objects)阅读有关此委托的更多信息。 60 | 61 | 例如,如果你已经在一个对象上像这样定义了一个 `inspect()` 函数: 62 | 63 | ``` javascript 64 | > var obj = {foo: 'this will not show up in the inspect() output'}; 65 | undefined 66 | > obj.inspect = () => { 67 | ... return {bar: 'baz'}; 68 | ... }; 69 | [Function] 70 | ``` 71 | 72 | 并试着在 REPL 中打印 `obj`,它将会调用自定义的 `inspect()` 函数: 73 | 74 | ``` bash 75 | > obj 76 | {bar: 'baz'} 77 | ``` -------------------------------------------------------------------------------- /errors/README.md: -------------------------------------------------------------------------------- 1 | # 错误(Errors) 2 | 3 | * [Error 类](./class_Error.md) 4 | * [SyntaxError 类](./class_SyntaxError.md) 5 | * [ReferenceError 类](./class_ReferenceError.md) 6 | * [RangeError 类](./class_RangeError.md) 7 | * [TypeError 类](./class_TypeError.md) 8 | * [错误的冒泡和捕捉](./error_propagation_and_interception.md) 9 | - [Node.js 风格的回调](./error_propagation_and_interception.md#nodejs-风格的回调) 10 | * [异常与错误](./exceptions_vs_errors.md) 11 | * [系统错误](./system_errors.md) 12 | - [系统错误类](./system_errors.md#系统错误类) 13 | - [通用的系统错误](./system_errors.md#通用的系统错误) 14 | 15 | -------------------------------------------------- 16 | 17 | 18 | 在 Node.js 中运行的应用一般会遇到以下四类错误: 19 | 20 | * 标准的 JavaScript 错误,例如: 21 | - [EvalError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/EvalError):当调用 `eval()` 失败时抛出。 22 | - [SyntaxError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError):当响应错误的 JavaScript 语法时抛出。 23 | - [RangeError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RangeError):当一个值不在预期范围内时抛出。 24 | - [ReferenceError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError):当使用未定义的变量时抛出。 25 | - [TypeError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypeError):当传递错误类型的参数时抛出。 26 | - [URIError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/URIError):当全局 URI 处理函数被误用时抛出。 27 | 28 | * 由于底层操作系统的限制引发的系统错误。例如,试图打开不存在的文件,试图向一个已关闭的套接字发送数据等; 29 | 30 | * 以及由应用程序代码触发的用户指定(User-specified)的错误。 31 | 32 | * 断言错误是一种特殊的错误类型,只要 Node.js 检测到不应该发生的异常逻辑违例,就可以触发错误。这些通常由 `assert` 模块引发。 33 | 34 | 由 Node.js 提出的所有 JavaScript 和系统错误都继承自或是标准的 JavaScript [错误](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Error)类的实例,并保证*至少*提供该类可用的属性。 -------------------------------------------------------------------------------- /modules/README.md: -------------------------------------------------------------------------------- 1 | # 模块(Modules) 2 | 3 | * [方法和属性](./module.md) 4 | * [核心模块](./core_modules.md) 5 | * [文件模块](./file_modules.md) 6 | * [模块包装器](./the_module_wrapper.md) 7 | * [将文件夹作为模块](./folders_as_modules.md) 8 | * [从 node_modules 文件夹加载模块](./loading_from_node_modules_folders.md) 9 | * [从全局文件夹加载模块](./loading_from_the_global_folders.md) 10 | * [循环](./cycles.md) 11 | * [缓存](./caching.md) 12 | * [模块缓存的注意事项](./caching.md#模块缓存的注意事项) 13 | * [访问主模块](./accessing_the_main_module.md) 14 | * [总的来说...](./all_together.md) 15 | * [附录:包管理器的技巧](./package_manager_tips.md) 16 | 17 | -------------------------------------------------- 18 | 19 | > 稳定度:3 - 已锁定 20 | 21 | Node.js 有一个简单的模块加载系统。在 Node.js 中,文件和模块是一一对应的(每个文件被视为一个单独的模块)。举个例子,`foo.js` 加载同一目录下的 `circle.js` 模块。 22 | 23 | `foo.js` 的内容: 24 | 25 | ``` javascript 26 | const circle = require('./circle.js'); 27 | console.log(`The area of a circle of radius 4 is ${circle.area(4)}`); 28 | ``` 29 | 30 | `circle.js` 的内容: 31 | 32 | ``` javascript 33 | const PI = Math.PI; 34 | 35 | exports.area = (r) => PI * r * r; 36 | 37 | exports.circumference = (r) => 2 * PI * r; 38 | ``` 39 | 40 | `circle.js` 模块导出了 `area()` 和 `circumference()` 两个函数。为了将函数和对象添加进你的模块根,你可以将它们添加到特殊的 `exports` 对象下。 41 | 42 | 模块内的本地变量是私有的,因为模块被 Node.js 包装在一个函数中(详见[模块包装器](./the_module_wrapper.md))。在这个例子中,变量 `PI` 就是 `circle.js` 私有的。 43 | 44 | 如果你希望将你的模块根导出为一个函数(比如构造函数)或一次导出一个完整的对象而不是每一次都创建一个属性,请赋值给 `module.exports` 而不是 `exports`。 45 | 46 | 下面,我将在 `bar.js` 中使用 `square` 模块导出的构造函数。 47 | 48 | ``` javascript 49 | const square = require('./square.js'); 50 | var mySquare = square(2); 51 | console.log(`The area of my square is ${mySquare.area()}`); 52 | ``` 53 | 54 | `square` 模块定义在 `square.js` 中: 55 | 56 | ``` javascript 57 | // 赋值给 exports 将不会修改模块,必须使用 module.exports 58 | module.exports = (width) => { 59 | return { 60 | area: () => width * width 61 | }; 62 | } 63 | ``` 64 | 65 | 模块系统在 `require("module")` 中实现。 -------------------------------------------------------------------------------- /dgram/dgram.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [dgram.createSocket(options[, callback])](#createsocket-options) 4 | * [dgram.createSocket(type[, callback])](#createsocket-type) 5 | 6 | -------------------------------------------------- 7 | 8 | ## dgram.createSocket(options[, callback]) 9 | 10 | * `options` {Object} 11 | 12 | * `callback` {Function} 作为 `'message'` 事件的一个附属监听器。 13 | 14 | * 返回:[dgram.Socket>](./class_dgram_Socket.md#) 15 | 16 | 创建一个 `dgram.Socket` 对象。`options` 参数是一个应该包含一个 `udp4` 或 `udp6` 的 `type` 字段和一个可选的 `reuseAddr` 布尔型字段的对象。 17 | 18 | 当 `reuseAddr` 为 `true` 时,[socket.bind()](./class_dgram_Socket.md#socketbindport-address-callback) 将重用该地址,即使另一个进程已经绑定了一个套接字。`reuseAddr` 默认为 `false`。一个可选的 `callback` 函数可以通过指定添加为 `'message'` 事件的一个监听器。 19 | 20 | 一旦创建了套接字,调用 [socket.bind()](./class_dgram_Socket.md#socketbindport-address-callback) 会指示套接字开始监听数据报消息。当 `address` 和 `port` 没有传给 [socket.bind()](./class_dgram_Socket.md#socketbindport-address-callback) 时,该方法将会在一个随机端口上绑定套接字到“所有接口”地址(它对 `udp4` 和 `udp6` 套接字都是正确的)。绑定的地址和端口可以使用 [socket.address().address](./class_dgram_Socket.md#socket.address) 和 [socket.address().port](./class_dgram_Socket.md#socket.address) 检索。 21 | 22 | 23 | ## dgram.createSocket(type[, callback]) 24 | 25 | * `type` {String} 既可以是 `'udp4'` 也可以是 `'udp6'` 26 | 27 | * `callback` {Function} 作为 `'message'` 事件的一个附属监听器。可选 28 | 29 | * 返回:[dgram.Socket>](./class_dgram_Socket.md#) 30 | 31 | 通过指定的 `type` 创建一个 `dgram.Socket` 对象。`type` 参数既可以是 `udp4`,也可以是 `udp6`。一个可选的 `callback` 函数可以通过指定添加为 `'message'` 事件的一个监听器。 32 | 33 | 一旦创建了套接字,调用 [socket.bind()](./class_dgram_Socket.md#socketbindport-address-callback) 会指示套接字开始监听数据报消息。当 `address` 和 `port` 没有传给 [socket.bind()](./class_dgram_Socket.md#socketbindport-address-callback) 时,该方法将会在一个随机端口上绑定套接字到“所有接口”地址(它对 `udp4` 和 `udp6` 套接字都是正确的)。绑定的地址和端口可以使用 [socket.address().address](./class_dgram_Socket.md#socket.address) 和 [socket.address().port](./class_dgram_Socket.md#socket.address) 检索。 -------------------------------------------------------------------------------- /zlib/zlib_class.md: -------------------------------------------------------------------------------- 1 | # 压缩解压类 2 | 3 | * [zlib.Zlib 类](#Zlib) 4 | - [zlib.flush([kind], callback)](#flush) 5 | - [zlib.params(level, strategy, callback)](#params) 6 | - [zlib.reset()](#reset) 7 | * [zlib.Gzip 类](#Gzip) 8 | * [zlib.Gunzip 类](#Gunzip) 9 | * [zlib.Unzip 类](#Unzip) 10 | * [zlib.Deflate 类](#Deflate) 11 | * [zlib.Inflate 类](#Inflate) 12 | * [zlib.DeflateRaw 类](#DeflateRaw) 13 | * [zlib.InflateRaw 类](#InflateRaw) 14 | 15 | -------------------------------------------------- 16 | 17 | 18 |
19 | ## zlib.Zlib 类 20 | 21 | 这个类未被 `zlib` 模块导出,编入此文档是因为它是其它压缩器/解压缩器的基类。 22 | 23 | 24 |
25 | ### zlib.flush([kind], callback) 26 | 27 | `kind` 默认为 `zlib.Z_FULL_FLUSH`。 28 | 29 | Flush 待处理的数据。请勿轻易调用此方法,过早的 flush 会影响压缩算法的有效性。 30 | 31 | 调用该方法只能 flush 从 zlib 获取的内部状态数据,并且不会执行任何流级别类型的 flushing。它的行为反而像一个正常的 `.write()` 回调,例如,当从流读出数据时,它被排着其他未处理的写入后面并且只会产生输出。 32 | 33 | 34 |
35 | ### zlib.params(level, strategy, callback) 36 | 37 | 动态更新压缩级别和压缩策略。仅适用于 deflate 算法。 38 | 39 | 40 |
41 | ### zlib.reset() 42 | 43 | 将压缩器/解压缩器重置为默认出厂值。仅对 inflate 和 deflate 算法有效。 44 | 45 | 46 |
47 | ## zlib.Gzip 类 48 | 49 | 使用 Gzip 压缩数据。 50 | 51 | 52 |
53 | ## zlib.Gunzip 类 54 | 55 | 解压缩一个 Gunzip 流。 56 | 57 | 58 |
59 | ## zlib.Unzip 类 60 | 61 | 通过自动检测报头来解压缩一个以 Gzip 或 Deflate 压缩的流。 62 | 63 | 64 |
65 | ## zlib.Deflate 类 66 | 67 | 使用 Deflate 压缩数据。 68 | 69 | 70 |
71 | ## zlib.Inflate 类 72 | 73 | 解压缩一个 Inflate 流。 74 | 75 | 76 |
77 | ## zlib.DeflateRaw 类 78 | 79 | 使用 DeflateRaw 压缩数据,并且不追加 Zlib 头。 80 | 81 | 82 |
83 | ## zlib.InflateRaw 类 84 | 85 | 解压缩一个 InflateRaw 流。 -------------------------------------------------------------------------------- /readline/class_Interface.md: -------------------------------------------------------------------------------- 1 | # Interface 类 2 | 3 | * [rl.write(data[, key])](#rlwritedatakey) 4 | * [rl.setPrompt(prompt)](#rlsetpromptprompt) 5 | * [rl.prompt([preserveCursor])](#rlpromptpreservecursor) 6 | * [rl.question(query, callback)](#rlquestionquery-callback) 7 | * [rl.pause()](#rlpause) 8 | * [rl.resume()](#rlresume) 9 | * [rl.close()](#rlclose) 10 | 11 | -------------------------------------------------- 12 | 13 | 表示具有输入和输出流的 readline 的接口类。 14 | 15 | 16 | ## rl.write(data[, key]) 17 | 18 | 向 `output` 流写入 `data`,除非在调用 `createInterface` 时,`output` 被设置为 `null` 或 `undefined`。`key` 是一个对象字面量表示的键序列;如果终端是 TTY,则可用。 19 | 20 | 这也会恢复 `input` 流,如果它已被暂停。 21 | 22 | 例子: 23 | 24 | ``` javascript 25 | rl.write('Delete me!'); 26 | // Simulate ctrl+u to delete the line written previously 27 | rl.write(null, {ctrl: true, name: 'u'}); 28 | ``` 29 | 30 | 31 | ## rl.setPrompt(prompt) 32 | 33 | 设置提示,例如,当你在命令行中运行 `node` 时,你会看到 `> `,这就是 Node.js 的提示。 34 | 35 | 36 | ## rl.prompt([preserveCursor]) 37 | 38 | 为用户的输入准备 readline,将当前的 `setPrompt` 选项放在一个新行上,给用户一个新的写点。设置 `preserveCursor` 为 `true`,防止将光标位置重置为 `0`。 39 | 40 | 这也会恢复用于 `createInterface` 的 `input` 流,如果它已被暂停。 41 | 42 | 当调用 `createInterface` 时,如果 `output` 被设置为 `null` 或 `undefined`,该提示不会写入。 43 | 44 | 45 | ## rl.question(query, callback) 46 | 47 | 在提示符前面加上 `query` 并带着用户响应调用 `callback`。向用户显示查询,然后在用户输入后,带着用户响应调用 `callback`。 48 | 49 | 这也会恢复用于 `createInterface` 的 `input` 流,如果它已被暂停。 50 | 51 | 当调用 `createInterface` 时,如果 `output` 被设置为 `null` 或 `undefined`,将不会显示。 52 | 53 | 用法示例: 54 | 55 | ``` javascript 56 | rl.question('What is your favorite food?', (answer) => { 57 | console.log(`Oh, so your favorite food is ${answer}`); 58 | }); 59 | ``` 60 | 61 | 62 | ## rl.pause() 63 | 64 | 暂停 readline 的 `input` 流,如果需要,可以在之后恢复。 65 | 66 | 请注意,这不会立即暂停事件流。在调用 `pause` 之后,可能会发出几个事件,包括 `line`。 67 | 68 | 69 | ## rl.resume() 70 | 71 | 恢复 readline 的 `input` 流。 72 | 73 | 74 | ## rl.close() 75 | 76 | 关闭 `Interface` 实例,放弃控制 `input` 和 `output` 流。也同样会发出 `'close'` 事件。 -------------------------------------------------------------------------------- /url/url.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [url.parse(urlStr[, parseQueryString][, slashesDenoteHost])](#urlparseurlstr-parsequerystring-slashesdenotehost) 4 | * [url.format(urlObj)](#urlformaturlobj) 5 | * [url.resolve(from, to)](#urlresolvefrom-to) 6 | 7 | -------------------------------------------------- 8 | 9 | 10 | URL 模块提供了以下方法: 11 | 12 | ## url.parse(urlStr[, parseQueryString][, slashesDenoteHost]) 13 | 14 | 取一个 URL 字符串,并返回一个对象。 15 | 16 | 给第二个参数传 `true`,会使用 `querystring` 模块解析查询字符串。如果为 `true`,那么 `query` 属性将总是被指定为一个对象,并且 `search` 属性总是一个(可能为空)字符串。如果 `false`,那么 `query` 属性将不会被解析或解码。默认为 `false`。 17 | 18 | 给第三个参数传 `true`,将会把 `//foo/bar` 作为 `{ host: 'foo', pathname: '/bar' }` 对待,而不是 `{ pathname: '//foo/bar' }`。默认为 `false`。 19 | 20 | 21 | ## url.format(urlObj) 22 | 23 | 取一个解析的 URL 对象,并返回一个格式化的 URL 字符串。 24 | 25 | 这里展示的是格式化过程是如何工作的: 26 | 27 | * `href` 会被忽略。 28 | 29 | * `path` 会被忽略。 30 | 31 | * `protocol` 有无尾 `:`(冒号)都被同等对待。 32 | 33 | - 只要 `host` / `hostname` 存在,`http`、`https`、`ftp`、`gopher`、`file` 协议会被补全后缀 `://`(冒号-斜线-斜线)。 34 | 35 | - 其他的协议 `mailto`、`xmpp`、`aim`、`sftp`、`foo` 等,会被补全后缀 `:`(冒号) 36 | 37 | * `slashes` 如果协议要求 `://`(冒号-斜线-斜线),设置为 `true`。 38 | 39 | - 只需要对此前未被列为需要斜杠的协议进行设置,如 `mongodb://localhost:8000/`,或假设 `host` / `hostname` 不存在。 40 | 41 | * `auth` 如果存在的话,会被使用。 42 | 43 | * `hostname` 如果 `host` 不存在的话才会被使用。 44 | 45 | * `port` 如果 `host` 不存在的话才会被使用。 46 | 47 | * `host` 会被用来代替 `hostname` 和 `port`。 48 | 49 | * `pathname` 对有无前导的 `/`(斜线)都一视同仁。 50 | 51 | * `query`(对象,详见 `querystring`)如果 `search` 不存在的话,会被使用。 52 | 53 | * `search` 会被用来代替 `query`。 54 | 55 | - 对有无前导的 `?`(问号)都一视同仁。 56 | 57 | * `hash` 对有无前导的 `#`(井号)都一视同仁。 58 | 59 | 60 | ## url.resolve(from, to) 61 | 62 | 取一个基础的 URL,和一个链接 URL,并解析它们作为一个浏览器可以理解的一个锚标记。例子: 63 | 64 | ``` javascript 65 | url.resolve('/one/two/three', 'four') // '/one/two/four' 66 | url.resolve('http://example.com/', '/one') // 'http://example.com/one' 67 | url.resolve('http://example.com/one', '/two') // 'http://example.com/two' 68 | ``` -------------------------------------------------------------------------------- /buffer/buffers_and_typedarray.md: -------------------------------------------------------------------------------- 1 | # Buffers和类型数组 2 | 3 | Buffers 同样是 `Uint8Array` 类型数组(TypedArray)的实例。但是,和 ECMAScript 2015 中的 `TypedArray` 规范还是有些微妙的不同之处。例如,当 `ArrayBuffer#slice()` 创建了一个切片的副本时,[Buffer#slice()](./class_Buffer.md#slice) 的实现是在现有的 Buffer 上不经过拷贝直接进行创建,这也使得 `Buffer#slice()` 更为有效。 4 | 5 | 在以下的注意事项下,从一个 Buffer 里创建一个新的类型数组(TypedArray)也是有可能的: 6 | 7 | 1. 将 Buffer 对象的内存以不共享的方式拷贝到这个类型数组(TypedArray)中。 8 | 9 | 2. 将 Buffer 对象的内存解释执行为一个不同元素的数组,并且不是目标类型的字节数组。这就像,`new Uint32Array(Buffer.from([1,2,3,4]))` 创建了一个4元素的 `Uint32Array` 的包含元素 `[1,2,3,4]` ,而不是 `Uint32Array` 包含一个单一的元素 `[0x1020304]` 或 `[0x4030201]` 。 10 | 11 | 也可以通过类型数组对象的 `.buffer` 属性创建一个新的 Buffer ,作为共享同一分配的内存的类型数组实例: 12 | 13 | ```javascript 14 | const arr = new Uint16Array(2); 15 | arr[0] = 5000; 16 | arr[1] = 4000; 17 | 18 | const buf1 = Buffer.from(arr); // copies the buffer 19 | const buf2 = Buffer.from(arr.buffer); // shares the memory with arr; 20 | 21 | console.log(buf1); 22 | // Prints: , copied buffer has only two elements 23 | console.log(buf2); 24 | // Prints: 25 | 26 | arr[1] = 6000; 27 | console.log(buf1); 28 | // Prints: 29 | console.log(buf2); 30 | // Prints: 31 | ``` 32 | 33 | 请注意,当通过类型数组的 `.buffer` 属性创建一个 Buffer 时,有可能只能通过传入 `byteOffset` 和 `length` 参数使用底层类型数组的一部分。 34 | 35 | ```javascript 36 | const arr = new Uint16Array(20); 37 | const buf = Buffer.from(arr.buffer, 0, 16); 38 | console.log(buf.length); 39 | // Prints: 16 40 | ``` 41 | 42 | `Buffer.from()` 和 [TypedArray.from()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/from) (如,`Uint8Array.from()`)有着不同的签名和实现。具体而言,类型数组的变种接受第二参数,在类型数组的每个元素上调用一个映射函数。 43 | 44 | 但 `Buffer.from()` 不支持使用一个映射函数: 45 | 46 | * [Buffer.from(array)](./class_Buffer.md#Buffer_from_array) 47 | 48 | * [Buffer.from(buffer)](./class_Buffer.md#Buffer_from_buffer) 49 | 50 | * [Buffer.from(arrayBuffer[, byteOffset[, length]])](./class_Buffer.md#Buffer_from_arrayBuffer) 51 | 52 | * [Buffer.from(str[, encoding])](./class_Buffer.md#Buffer_from_str) -------------------------------------------------------------------------------- /fs/README.md: -------------------------------------------------------------------------------- 1 | # 文件系统(File System) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | 文件 I/O 是由简单封装的标准 POSIX 函数提供。使用该模块使用 `require('fs')`。所有的方法都异步和同步形式。 6 | 7 | 异步形式始终以完成时的回调作为最后一个参数。传递给完成时的回调的参数取决于方法,但第一个参数总是留给异常。如果操作成功完成,则第一个参数将是 `null` 或 `undefined`。 8 | 9 | 当使用异步形式时,任何的异常都会被立即抛出。你可以使用 try/catch 来处理异常,或让它们冒泡。 10 | 11 | 这里是异步版本的例子: 12 | 13 | ``` javascript 14 | const fs = require('fs'); 15 | 16 | fs.unlink('/tmp/hello', (err) => { 17 | if (err) throw err; 18 | console.log('successfully deleted /tmp/hello'); 19 | }); 20 | ``` 21 | 22 | 这里是同步版本的例子: 23 | 24 | ``` javascript 25 | const fs = require('fs'); 26 | 27 | fs.unlinkSync('/tmp/hello'); 28 | console.log('successfully deleted /tmp/hello'); 29 | ``` 30 | 31 | 异步方法没法保证执行顺序。所以下面例子容易出错: 32 | 33 | ``` javascript 34 | fs.rename('/tmp/hello', '/tmp/world', (err) => { 35 | if (err) throw err; 36 | console.log('renamed complete'); 37 | }); 38 | fs.stat('/tmp/world', (err, stats) => { 39 | if (err) throw err; 40 | console.log(`stats: ${JSON.stringify(stats)}`); 41 | }); 42 | ``` 43 | 44 | `fs.stat` 也可以在 `fs.rename` 之前执行。要做到这一点,正确的方法是采用回调链。 45 | 46 | ``` javascript 47 | fs.rename('/tmp/hello', '/tmp/world', (err) => { 48 | if (err) throw err; 49 | fs.stat('/tmp/world', (err, stats) => { 50 | if (err) throw err; 51 | console.log(`stats: ${JSON.stringify(stats)}`); 52 | }); 53 | }); 54 | ``` 55 | 56 | 在忙碌的进程中,*强烈推荐*开发者使用这些函数的异步版本。同步版本将会阻止整个进程,直到他们完成——停止所有连接。 57 | 58 | 可使用文件名的相对路径。但请记住,该路径将相对 `process.cwd()`。 59 | 60 | 大多数 fs 函数,让你忽略回调参数。如果你这么做,一个默认的回调将用于抛出错误。为了得到一个到原来的调用点的跟踪,设置 `NODE_DEBUG` 环境变量: 61 | 62 | ``` bash 63 | $ cat script.js 64 | function bad() { 65 | require('fs').readFile('/'); 66 | } 67 | bad(); 68 | 69 | $ env NODE_DEBUG=fs node script.js 70 | fs.js:66 71 | throw err; 72 | ^ 73 | Error: EISDIR, read 74 | at rethrow (fs.js:61:21) 75 | at maybeCallback (fs.js:79:42) 76 | at Object.fs.readFile (fs.js:153:18) 77 | at bad (/path/to/script.js:2:17) 78 | at Object. (/path/to/script.js:5:1) 79 | 80 | ``` -------------------------------------------------------------------------------- /debugger/README.md: -------------------------------------------------------------------------------- 1 | # 调试器(Debugger) 2 | 3 | > 稳定度:2 - 稳定 4 | 5 | Node.js 包含一个可以有效地通过 [TCP 协议](https://github.com/v8/v8/wiki/Debugging-Protocol) 访问的完整的进程外的全功能调试工具并内置调试客户端。在启动 Node.js 后,通过 `debug` 参数加上需要调试的脚本文件路径的方式使用,在调试器成功启动后会有明显的提示: 6 | 7 | ``` 8 | $ node debug myscript.js 9 | < debugger listening on port 5858 10 | connecting... ok 11 | break in /home/indutny/Code/git/indutny/myscript.js:1 12 | 1 x = 5; 13 | 2 setTimeout(() => { 14 | 3 debugger; 15 | debug> 16 | ``` 17 | 18 | Node.js 的调试器客户端虽然目前还没法支持全部命令,但可以进行一些简单的(调试)步骤和检测(命令)。 19 | 20 | 在脚本的源代码中插入一个 `debugger;` 声明就可以在当前位置的代码中设置一个断点。 21 | 22 | 例如,假设 `myscript.js` 是这么写的: 23 | 24 | ```javascript 25 | // myscript.js 26 | x = 5; 27 | setTimeout(() => { 28 | debugger; 29 | console.log('world'); 30 | }, 1000); 31 | console.log('hello'); 32 | ``` 33 | 34 | 一旦运行调试器,将在第4行发生断点: 35 | 36 | ``` 37 | // myscript.js 38 | x = 5; 39 | setTimeout(() => { 40 | debugger; 41 | console.log('world'); 42 | }, 1000); 43 | console.log('hello'); 44 | Once the debugger is run, a breakpoint will occur at line 4: 45 | 46 | $ node debug myscript.js 47 | < debugger listening on port 5858 48 | connecting... ok 49 | break in /home/indutny/Code/git/indutny/myscript.js:1 50 | 1 x = 5; 51 | 2 setTimeout(() => { 52 | 3 debugger; 53 | debug> cont 54 | < hello 55 | break in /home/indutny/Code/git/indutny/myscript.js:3 56 | 1 x = 5; 57 | 2 setTimeout(() => { 58 | 3 debugger; 59 | 4 console.log('world'); 60 | 5 }, 1000); 61 | debug> next 62 | break in /home/indutny/Code/git/indutny/myscript.js:4 63 | 2 setTimeout(() => { 64 | 3 debugger; 65 | 4 console.log('world'); 66 | 5 }, 1000); 67 | 6 console.log('hello'); 68 | debug> repl 69 | Press Ctrl + C to leave debug repl 70 | > x 71 | 5 72 | > 2+2 73 | 4 74 | debug> next 75 | < world 76 | break in /home/indutny/Code/git/indutny/myscript.js:5 77 | 3 debugger; 78 | 4 console.log('world'); 79 | 5 }, 1000); 80 | 6 console.log('hello'); 81 | 7 82 | debug> quit 83 | ``` 84 | 85 | `repl` 命令允许代码被远程评估。`next` 命令用于跳转到下一行。键入 `help` 可以查看其他的有效命令。 -------------------------------------------------------------------------------- /timers/scheduling_timers.md: -------------------------------------------------------------------------------- 1 | # 预定定时器 2 | 3 | * [setTimeout(callback, delay[, ...args])](#settimeoutcallback-delay-args) 4 | * [setInterval(callback, delay[, ...args])](#setintervalcallback-delay-args) 5 | * [setImmediate(callback[, ...args])](#setimmediatecallback-args) 6 | 7 | -------------------------------------------------- 8 | 9 | Node.js 中的计时器是一种会在一段时间后调用给定的函数的内部构造。定时器函数会在何时被调用,取决于用来创建定时器的方法以及 Node.js 事件循环是否正在做其他工作。 10 | 11 | 12 | ## setTimeout(callback, delay[, ...args]) 13 | 14 | 添加:v0.0.1 15 | 16 | * `callback` {Function} 当定时器到点时回调的函数。 17 | 18 | * `delay` {Number} 在调用 `callback` 之前等待的毫秒数。 19 | 20 | * `...args` {Any} 在调用 `callback` 时要传递的可选参数。 21 | 22 | 在 `delay` 毫秒之后预定执行一次性的 `callback`。返回一个用于 [clearTimeout()](./cancelling_timers.md#cleartimeouttimeout) 的 `Timeout`。 23 | 24 | `callback` 可能不会精确地在 `delay` 毫秒被调用。Node.js 不能保证回调被触发的确切时间,也不能保证它们的顺序。回调会在尽可能接近所指定的时间上调用。 25 | 26 | *注意*:当 `delay` 大于 `2147483647` 或小于 `1` 时,`delay` 会被设置为 `1`。 27 | 28 | 如果 `callback` 不是一个函数,将会抛出一个 [TypeError](../errors/class_TypeError.md)。 29 | 30 | 31 | ## setInterval(callback, delay[, ...args]) 32 | 33 | 添加:v0.0.1 34 | 35 | * `callback` {Function} 当定时器到点时回调的函数。 36 | 37 | * `delay` {Number} 在调用 `callback` 之前等待的毫秒数。 38 | 39 | * `...args` {Any} 在调用 `callback` 时要传递的可选参数。 40 | 41 | 预定每隔 `delay` 毫秒重复执行 `callback`。返回一个用于 [clearInterval()](./cancelling_timers.md#clearintervaltimeout) 的 `Timeout`。 42 | 43 | *注意*:当 `delay` 大于 `2147483647` 或小于 `1` 时,`delay` 会被设置为 `1`。 44 | 45 | 如果 `callback` 不是一个函数,将会抛出一个 [TypeError](../errors/class_TypeError.md)。 46 | 47 | 48 | ## setImmediate(callback[, ...args]) 49 | 50 | 添加:v0.9.1 51 | 52 | * `callback` {Function} 在当前的 Node.js 事件循环回合结束时调用该函数。 53 | 54 | * `...args` {Any} 在调用 `callback` 时要传递的可选参数。 55 | 56 | 预定“立即”执行 `callback`,它是在 I/O 事件的回调之后并在使用 [setTimeout()](settimeoutcallback-delay-args) 和 [setInterval()](setintervalcallback-delay-args) 创建的计时器之前被触发。返回一个用于 [clearImmediate()](./cancelling_timers.md#clearimmediateimmediate) 的 `Immediate`。 57 | 58 | 当多次调用 `setImmediate()` 时,回调函数会按照它们的创建顺序依次执行。每个事件循环迭代都会处理整个回调队列。如果立即定时器正在执行回调中排队,那么该定时器直到下一个事件循环迭代之前将不会被触发。 59 | 60 | 如果 `callback` 不是一个函数,将会抛出一个 [TypeError](../errors/class_TypeError.md)。 -------------------------------------------------------------------------------- /crypto/class_Certificate.md: -------------------------------------------------------------------------------- 1 | # Certificate类 2 | 3 | * [new crypto.Certificate()](#new-cryptocertificate) 4 | * [certificate.exportPublicKey(spkac)](#certificateexportpublickeyspkac) 5 | * [certificate.exportChallenge(spkac)](#certificateexportchallengespkac) 6 | * [certificate.verifySpkac(spkac)](#certificateverifyspkacspkac) 7 | 8 | -------------------------------------------------- 9 | 10 | SPKAC 是 Netscape 最初实现的证书签名请求机制并且现在正式指定为 [HTML5 的 keygen 元素](http://www.w3.org/TR/html5/forms.html#the-keygen-element)的一部分。 11 | 12 | `crypto` 模块提供了 `Certificate` 类用于处理 SPKAC 数据。最常见的用法是处理 HTML5 `` 元素生成的输出。Node.js 内部使用 OpenSSL 的 SPKAC 来实现。 13 | 14 | 15 | ## new crypto.Certificate() 16 | 17 | `Certificate` 类的实例可以通过使用 `new` 关键词或调用 `crypto.Certificate()` 函数来创建: 18 | 19 | ``` javascript 20 | const crypto = require('crypto'); 21 | 22 | const cert1 = new crypto.Certificate(); 23 | const cert2 = crypto.Certificate(); 24 | ``` 25 | 26 | 27 | ## certificate.exportPublicKey(spkac) 28 | 29 | `spkac` 数据结构包括公钥和咨询。`certificate.exportPublicKey()` 以 Node.js 的 [Buffer](../buffer/) 形式返回公钥组件。`spkac` 参数既可以是字符串也可以是 [Buffer](../buffer/)。 30 | 31 | ``` javascript 32 | const cert = require('crypto').Certificate(); 33 | const spkac = getSpkacSomehow(); 34 | const publicKey = cert.exportPublicKey(spkac); 35 | console.log(publicKey); 36 | // Prints the public key as 37 | ``` 38 | 39 | 40 | ## certificate.exportChallenge(spkac) 41 | 42 | `spkac` 数据结构包括公钥和咨询。`certificate.exportChallenge()` 以 Node.js 的 [Buffer](../buffer/) 形式返回公钥组件。`spkac` 参数既可以是字符串也可以是 [Buffer](../buffer/)。 43 | 44 | ``` javascript 45 | const cert = require('crypto').Certificate(); 46 | const spkac = getSpkacSomehow(); 47 | const challenge = cert.exportChallenge(spkac); 48 | console.log(challenge.toString('utf8')); 49 | // Prints the challenge as a UTF8 string 50 | ``` 51 | 52 | 53 | ## certificate.verifySpkac(spkac) 54 | 55 | 如果给定的 `spkac` 数据结构有效,则返回 `true`,否则,返回 `false`。`spkac` 参数必须是 Node.js 的 [Buffer](../buffer/) 形式。 56 | 57 | ``` javascript 58 | const cert = require('crypto').Certificate(); 59 | const spkac = getSpkacSomehow(); 60 | console.log(cert.verifySpkac(new Buffer(spkac))); 61 | // Prints true or false 62 | ``` -------------------------------------------------------------------------------- /debugger/commands_reference.md: -------------------------------------------------------------------------------- 1 | # 命令参考 2 | 3 | * [步进](#stepping) 4 | * [断点](#breakpoints) 5 | * [信息](#info) 6 | * [执行控制](#execution_control) 7 | * [杂项](#various) 8 | 9 | -------------------------------------------------- 10 | 11 | 12 |
13 | ## 步进 14 | 15 | * `cont`,`c` - 继续执行 16 | 17 | * `next`,`n` - 下一步 18 | 19 | * `step`,`s` - 介入 20 | 21 | * `out`,`o` - 退出介入 22 | 23 | * `pause` - 暂停执行代码(类似开发者工具中的暂停按钮) 24 | 25 | 26 |
27 | ## 断点 28 | 29 | * `setBreakpoint()`,`sb()` - 在当前行设置断点 30 | 31 | * `setBreakpoint(line)`,`sb(line)` - 在指定行设置断点 32 | 33 | * `setBreakpoint('fn()')`,`sb(...)` - 在函数体的第一条语句设置断点 34 | 35 | * `setBreakpoint('script.js', 1)`,`sb(...)` - 在 script.js 的第一行设置断点 36 | 37 | * `clearBreakpoint('script.js', 1)`,`cb(...)` - 清除 script.js 第一行的断点 38 | 39 | 也可以在一个尚未被加载的文件(模块)中设置断点: 40 | 41 | ``` 42 | $ ./node debug test/fixtures/break-in-module/main.js 43 | < debugger listening on port 5858 44 | connecting to port 5858... ok 45 | break in test/fixtures/break-in-module/main.js:1 46 | 1 var mod = require('./mod.js'); 47 | 2 mod.hello(); 48 | 3 mod.hello(); 49 | debug> setBreakpoint('mod.js', 23) 50 | Warning: script 'mod.js' was not loaded yet. 51 | 1 var mod = require('./mod.js'); 52 | 2 mod.hello(); 53 | 3 mod.hello(); 54 | debug> c 55 | break in test/fixtures/break-in-module/mod.js:23 56 | 21 57 | 22 exports.hello = () => { 58 | 23 return 'hello from module'; 59 | 24 }; 60 | 25 61 | debug> 62 | ``` 63 | 64 | 65 |
66 | ## 信息 67 | 68 | * `backtrace`,`bt` - 显示当前执行框架的回溯 69 | 70 | * `list(5)` - 显示脚本源代码的 5 行上下文(之前 5 行和之后 5 行) 71 | 72 | * `watch(expr)` - 向监视列表添加表达式 73 | 74 | * `unwatch(expr)` - 从监视列表移除表达式 75 | 76 | * `watchers` - 列出所有监视器和它们的值(每个断点会自动列出) 77 | 78 | * `repl` - 在所调试的脚本的上下文中打开调试器的REPL进行评估 79 | 80 | * `exec expr` - 在所调试的脚本的上下文中执行一个表达式 81 | 82 | 83 |
84 | ## 执行控制 85 | 86 | * `run` - 运行脚本(调试器开始时自动运行) 87 | 88 | * `restart` - 重新启动脚本 89 | 90 | * `kill` - 终止脚本 91 | 92 | 93 |
94 | ## 杂项 95 | 96 | * `scripts` - 列出所有已加载的脚本 97 | 98 | * `version` - 显示 V8 引擎的版本号 -------------------------------------------------------------------------------- /crypto/class_Hash.md: -------------------------------------------------------------------------------- 1 | # Hash类 2 | 3 | * [hash.update(data[, input_encoding])](#hashupdatedata-inputencoding) 4 | * [hash.digest([encoding])](#hashdigestencoding) 5 | 6 | -------------------------------------------------- 7 | 8 | `Hash` 类是用于创建数据散列摘要的工具类。它可以以两种方式之一使用: 9 | 10 | * 作为可读和可写的[流](../stream/),写入数据并在可读端产生计算后的散列摘要。 11 | 12 | * 使用 [hash.update()](#hashupdatedata-inputencoding) 和 [hash.digest()](#hashdigestencoding) 产生计算后的散列。 13 | 14 | [crypto.createHash()](./crypto.md#cryptocreatehashalgorithm) 方法用于创建 `Hash` 实例。`Hash` 对象无法直接使用 `new` 关键词创建。 15 | 16 | 示例:将 `Hash` 对象用作流: 17 | 18 | ``` javascript 19 | const crypto = require('crypto'); 20 | const hash = crypto.createHash('sha256'); 21 | 22 | hash.on('readable', () => { 23 | var data = hash.read(); 24 | if (data) 25 | console.log(data.toString('hex')); 26 | // Prints: 27 | // 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50 28 | }); 29 | 30 | hash.write('some data to hash'); 31 | hash.end(); 32 | ``` 33 | 34 | 示例:使用 `Hash` 并导流: 35 | 36 | ``` javascript 37 | const crypto = require('crypto'); 38 | const fs = require('fs'); 39 | const hash = crypto.createHash('sha256'); 40 | 41 | const input = fs.createReadStream('test.js'); 42 | input.pipe(hash).pipe(process.stdout); 43 | ``` 44 | 45 | 示例:使用 [hash.update()](#hashupdatedata-inputencoding) 和 [hash.digest()](#hashdigestencoding) 方法: 46 | 47 | ``` javascript 48 | const crypto = require('crypto'); 49 | const hash = crypto.createHash('sha256'); 50 | 51 | hash.update('some data to hash'); 52 | console.log(hash.digest('hex')); 53 | // Prints: 54 | // 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50 55 | ``` 56 | 57 | 58 | ## hash.update(data[, input_encoding]) 59 | 60 | 使用给定的 `data` 更新哈希内容,给出的 `input_encoding` 编码,可以是 `'utf8'`、`'ascii'` 或 `'binary'`。如果没有提供 `encoding`,同时 `data` 是一个字符串,将强制使用 `'binary'` 编码。如果 `data` 是一个 [Buffer](../buffer/),那么 `input_encoding` 参数会被忽略。 61 | 62 | 当它作为流时,可以在新数据上多次调用。 63 | 64 | 65 | ## hash.digest([encoding]) 66 | 67 | 计算所有传入的数据的散列摘要(使用 [hash.update()](#hashupdatedata-inputencoding) 方法)。`encoding` 可以是 `'hex'`、`'binary'` 或 `'base64'`。如果提供了 `encoding`,会返回一个字符串;否则返回一个 [Buffer](../buffer/)。 68 | 69 | 在调用 `hash.digest()` 方法之后,`Hash` 对象将不能再次使用。多次调用将导致抛出错误。 -------------------------------------------------------------------------------- /fs/class_fs_Stats.md: -------------------------------------------------------------------------------- 1 | # fs.Stats类 2 | 3 | * [状态时间值](#stat_time_values) 4 | 5 | -------------------------------------------------- 6 | 7 | 8 | 从 [fs.stat()](#stat)、[fs.lstat()](#lstat) 和 [fs.fstat()](#fstat) 及其同步版本返回的对象都属于这种类型。 9 | 10 | * `stats.isFile()` 11 | 12 | * `stats.isDirectory()` 13 | 14 | * `stats.isBlockDevice()` 15 | 16 | * `stats.isCharacterDevice()` 17 | 18 | * `stats.isSymbolicLink()`(只在 [fs.lstat()](#lstat) 中有效) 19 | 20 | * `stats.isFIFO()` 21 | 22 | * `stats.isSocket()` 23 | 24 | 对于一个普通文件,[util.inspect(stats)](../util/util.md#inspect) 将返回非常类似这样的字符串: 25 | 26 | ``` javascript 27 | { 28 | dev: 2114, 29 | ino: 48064969, 30 | mode: 33188, 31 | nlink: 1, 32 | uid: 85, 33 | gid: 100, 34 | rdev: 0, 35 | size: 527, 36 | blksize: 4096, 37 | blocks: 8, 38 | atime: Mon, 10 Oct 2011 23:24:11 GMT, 39 | mtime: Mon, 10 Oct 2011 23:24:11 GMT, 40 | ctime: Mon, 10 Oct 2011 23:24:11 GMT, 41 | birthtime: Mon, 10 Oct 2011 23:24:11 GMT 42 | } 43 | ``` 44 | 45 | 请注意 `atime`、`mtime`、`birthtime` 和 `ctime` 是 [Date](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date) 对象的实例,比较这些对象的值,你应该使用合适的方法。对于大多数一般用途 [getTime()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime) 会返回自 *1 January 1970 00:00:00 UTC* 已过的毫秒数并且该整数足以拿来做任何比较,然而也有可用于显示模糊信息的其他方法。更多的细节可以在 [MDN JavaScript的参考页](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date) 中找到。 46 | 47 | 48 |
49 | ## 状态时间值 50 | 51 | 在状态对象中的时间有以下语义: 52 | 53 | * `atime` “访问时间” - 文件数据最后被访问的时间。会被 `mknod(2)`、`utimes(2)` 和 `read(2)` 系统调用更改。 54 | 55 | * `mtime` “修改时间” - 文件数据最后被修改的时间。会被 `mknod(2)`、`utimes(2)` 和 `write(2)` 系统调用更改。 56 | 57 | * `ctime` “更改时间” - 文件状态上次更改的时间(索引节点数据修改)。会被 `chmod(2)`、`chown(2)`、`link(2)`、`mknod(2)`、`rename(2)`、`unlink(2)`、`utimes(2)`、`read(2)` 和 `write(2)`系统调用更改。 58 | 59 | * `birthtime` “出生时间” - 文件创建的时间。在创建文件时设定一次。在文件系统中出生日期不可用,这个字段可能代替保存 `ctime` 或 `1970-01-01T00:00Z`(如,Unix 的纪元时间戳 `0`)两者任一。注意,此值也许比在此情况下的 `atime` 或 `mtime` 更加有用。在 Darwin 和其它的 FreeBSD 衍生系统中,如果时间被明确设置到了一个比目前出生时间较早的值,也会设置使用 `utimes(2)` 系统调用。 60 | 61 | 在 Node.js v0.12 之前的版本中,在 Windows 系统中,`ctime` 保存 `birthtime`。请注意在 v0.12 中,`ctime` 不是“创建时间”,并且在 Unix 系统中,它从来都不是。 -------------------------------------------------------------------------------- /crypto/class_Hmac.md: -------------------------------------------------------------------------------- 1 | # Hmac类 2 | 3 | * [hmac.update(data[, input_encoding])](#hmacupdatedata-inputencoding) 4 | * [hmac.digest([encoding])](#hmacdigestencoding) 5 | 6 | -------------------------------------------------- 7 | 8 | `Hmac` 类是用于创建加密的 HMAC 摘要的工具类。它可以以两种方式之一使用: 9 | 10 | * 作为可读和可写的[流](../stream/),写入数据并在可读端产生计算后的 HMAC 摘要。 11 | 12 | * 使用 [hmac.update()](#hmacupdatedata-inputencoding) 和 [hmac.digest()](#hmacdigestencoding) 产生计算后的 HMAC 摘要。 13 | 14 | [crypto.createHmac()](./crypto.md##cryptocreatehmacalgorithm-key) 方法用于创建 `Hmac` 实例。`Hmac` 对象无法直接使用 `new` 关键词创建。 15 | 16 | 示例:将 `Hmac` 对象用作流: 17 | 18 | ``` javascript 19 | const crypto = require('crypto'); 20 | const hmac = crypto.createHmac('sha256', 'a secret'); 21 | 22 | hmac.on('readable', () => { 23 | var data = hmac.read(); 24 | if (data) 25 | console.log(data.toString('hex')); 26 | // Prints: 27 | // 7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e 28 | }); 29 | 30 | hmac.write('some data to hash'); 31 | hmac.end(); 32 | ``` 33 | 34 | 示例:使用 `Hmac` 并导流: 35 | 36 | ``` javascript 37 | const crypto = require('crypto'); 38 | const fs = require('fs'); 39 | const hmac = crypto.createHmac('sha256', 'a secret'); 40 | 41 | const input = fs.createReadStream('test.js'); 42 | input.pipe(hmac).pipe(process.stdout); 43 | ``` 44 | 45 | 示例:使用 [hmac.update()](#hmacupdatedata-inputencoding) 和 [hmac.digest()](#hmacdigestencoding) 方法: 46 | 47 | ``` javascript 48 | const crypto = require('crypto'); 49 | const hmac = crypto.createHmac('sha256', 'a secret'); 50 | 51 | hmac.update('some data to hash'); 52 | console.log(hmac.digest('hex')); 53 | // Prints: 54 | // 7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e 55 | ``` 56 | 57 | 58 | ## hmac.update(data[, input_encoding]) 59 | 60 | 使用给定的 `data` 更新 HMAC 内容,给出的 `input_encoding` 编码,可以是 `'utf8'`、`'ascii'` 或 `'binary'`。如果没有提供 `encoding`,同时 `data` 是一个字符串,将强制使用 `'binary'` 编码。如果 `data` 是一个 [Buffer](../buffer/),那么 `input_encoding` 参数会被忽略。 61 | 62 | 当它作为流时,可以在新数据上多次调用。 63 | 64 | 65 | ## hmac.digest([encoding]) 66 | 67 | 计算所有传入的的数据的 HMAC 摘要(使用 [hmac.update()](#hmacupdatedata-inputencoding) 方法)。`encoding` 可以是 `'hex'`、`'binary'` 或 `'base64'`。如果提供了 `encoding`,会返回一个字符串;否则返回一个 [Buffer](../buffer/)。 68 | 69 | 在调用 `hmac.digest()` 方法之后,`Hmac` 对象将不能再次使用。多次调用将导致抛出错误。 -------------------------------------------------------------------------------- /crypto/class_Verify.md: -------------------------------------------------------------------------------- 1 | # Verify类 2 | 3 | * [verifier.update(data[, input_encoding])](#verifierupdatedata-inputencoding) 4 | * [verifier.verify(object, signature[, signature_format])](#verifierverifyobject-signature-signatureformat) 5 | 6 | -------------------------------------------------- 7 | 8 | `Verify` 类是用于验证签名的工具类。它可以以两种方式之一使用: 9 | 10 | * 作为一个可写[流](../stream/),写入数据用于根据所提供的签名进行验证。 11 | 12 | * 使用 [verify.update()](#verifierupdatedata-inputencoding) 和 [verify.verify()](#verifierverifyobject-signature-signatureformat) 方法来验证签名。 13 | 14 | [crypto.createVerify()](./crypto.md#cryptocreateverifyalgorithm) 方法用于创建 `Verify` 实例。`Verify` 对象无法直接使用 `new` 关键词创建。 15 | 16 | 示例:将 `Verify` 对象用作流: 17 | 18 | ``` javascript 19 | const crypto = require('crypto'); 20 | const verify = crypto.createVerify('RSA-SHA256'); 21 | 22 | verify.write('some data to sign'); 23 | verify.end(); 24 | 25 | const public_key = getPublicKeySomehow(); 26 | const signature = getSignatureToVerify(); 27 | console.log(sign.verify(public_key, signature)); 28 | // Prints true or false 29 | ``` 30 | 31 | 示例:使用 [verify.update()](#verifierupdatedata-inputencoding) 和 [verify.verify()](#verifierverifyobject-signature-signatureformat) 方法: 32 | 33 | ``` javascript 34 | const crypto = require('crypto'); 35 | const verify = crypto.createVerify('RSA-SHA256'); 36 | 37 | verify.update('some data to sign'); 38 | 39 | const public_key = getPublicKeySomehow(); 40 | const signature = getSignatureToVerify(); 41 | console.log(verify.verify(public_key, signature)); 42 | // Prints true or false 43 | ``` 44 | 45 | 46 | ## verifier.update(data[, input_encoding]) 47 | 48 | 用给定的 `data` 更新 `Verify` 内容,给出的 `input_encoding` 编码,可以是 `'utf8'`、`'ascii'` 或 `'binary'`。如果没有提供 `encoding`,同时 `data` 是一个字符串,将强制使用 `'utf8'` 编码。如果 `data` 是一个 [Buffer](../buffer/),那么 `input_encoding` 参数会被忽略。 49 | 50 | 当它作为流时,可以在新数据上多次调用。 51 | 52 | 53 | ## verifier.verify(object, signature[, signature_format]) 54 | 55 | 使用给定的 `object` 和 `signature` 验证提供的数据。`object` 参数是一个包含 PEM 编码对象的字符串,它可以是 RSA 公钥、DSA 公钥或一个 X.509 证书。`signature` 参数是先前计算的数据的签名,`signature_format` 可以是 `'binary'`、`'hex'` 或 `'base64'`。如果指定了 `signature_format`,`signature` 期望是一个字符串,否则期望是一个 [Buffer](../buffer/)。 56 | 57 | 返回 `true` 或 `false` 取决于数据和公钥的签名的有效性。 58 | 59 | 在调用 `verify.verify()` 方法之后,`Verify` 对象将不能再次使用。多次调用 `verify.verify()` 将导致抛出错误。 -------------------------------------------------------------------------------- /buffer/other.md: -------------------------------------------------------------------------------- 1 | # Buffer.from(), Buffer.alloc(), and Buffer.allocUnsafe() 2 | 3 | * [是什么使得 Buffer.allocUnsafe(size) “不安全”?](#why) 4 | 5 | -------------------------------------------------- 6 | 7 | 8 | 由于历史原因,`Buffer` 实例通过 `Buffer` 构造函数创建,它基于提供的不同参数分配返回不同的 `Buffer` : 9 | 10 | * 给 `Buffer()` 的第一个参数传参(如,`new Buffer(10)`),通过指定的大小分配一个新的 Buffer 。给这样的 Buffer 分配的内存是*没有初始化*过的,并*会包含敏感数据*。这样的 `Buffer` 对象*必须手动*通过 [buf.fill(0)](./class_Buffer.md#fill) 初始化或写满这个 `Buffer` 。虽然这种行为是为了提高性能而*故意为之*的,开发经验已经证明对于是创造一个更慢但很安全的 `Buffer` 还是创建一个快速但未初始化的 `Buffer` 之间需要更加明确的区分。 11 | 12 | * 通过给第一个参数传字符串、数组或 Buffer ,可以将所传对象的数据拷贝当前 Buffer 中。 13 | 14 | * 传一个 `ArrayBuffer` 返回一个与给定的 `ArrayBuffer` 共享分配的内存的 `Buffer` 。 15 | 16 | 因为 `new Buffer()` 行为会根据第一个参数所传值的类型不同而显著改变,所以应用程序如果没有适当地验证给 `new Buffer()` 传的输入参数,或未能适当地初始化新分配的 `Buffer` 的内容,会给他们的代码带来安全性和可靠性方面的问题。 17 | 18 | 为了使创建的 `Buffer` 对象更可靠,更不容易出错,新的 `Buffer.from()`、 `Buffer.alloc()` 和 `Buffer.allocUnsafe()` 方法作为创建 `Buffer` 实例的替代手段而相继出台。 19 | 20 | 开发者*应当把所有正在使用的 `new Buffer()` 构造函数迁移到这些新的API之一*: 21 | 22 | * [Buffer.from(array)](./class_Buffer.md#Buffer_from_array) 返回一个包含所提供的 8位字节*的副本*的新 `Buffer` 。 23 | 24 | * [Buffer.from(arrayBuffer[, byteOffset[, length]])](./class_Buffer.md#Buffer_from_arrayBuffer) 返回一个与给定的 `ArrayBuffer` *共享*分配的内存的 `Buffer` 。 25 | 26 | * [Buffer.from(buffer)](./class_Buffer.md#Buffer_from_buffer) 返回一个包含所提供的 `Buffer` *的副本*的新 `Buffer` 。 27 | 28 | * [Buffer.from(str[, encoding])](./class_Buffer.md#Buffer_from_str) 返回一个包含所提供的字符串的*副本*的新 `Buffer` 。 29 | 30 | * [Buffer.alloc(size[, fill[, encoding]])](./class_Buffer.md#Buffer_alloc) 返回一个指定大小的被填满的 `Buffer` 实例。这种方法会比 [Buffer.allocUnsafe(size)](./class_Buffer.md#Buffer_allocUnsafe) 显著地慢,但可确保新创建的 `Buffer` 绝不会包含旧的和潜在的敏感数据。 31 | 32 | * [Buffer.allocUnsafe(size)](./class_Buffer.md#Buffer_allocUnsafe) 返回一个指定 `size` 的 `Buffer` ,但它的内容*必须*被 [buf.fill(0)](./class_Buffer.md#fill) 初始化或完全写满。 33 | 34 | 被 `Buffer.allocUnsafe(size)` 返回的 `Buffer` 实例,如果它的 `size` 小于或等于 `Buffer.poolSize` 的一半,可能被分配进一个共享的内部内存池。 35 | 36 | 37 |
38 | ### 是什么使得 Buffer.allocUnsafe(size) “不安全”? 39 | 40 | 当调用 `Buffer.allocUnsafe()` 时,被分配的内存段是*没被初始化*(它不是被零填充的)过的。虽然这样的设计使得内存的分配相当快,但已分配的存储段可能包含潜在的敏感的旧数据。使用通过 `Buffer.allocUnsafe(size)` 创建没有被*完全*覆写内存的 `Buffer` ,在 `Buffer` 内存是可读的情况下,可能泄露它的旧数据。 41 | 42 | 虽然在使用 `Buffer.allocUnsafe()` 时有明显的性能优势,但必须额外小心,以避免给应用程序引入安全漏洞。 -------------------------------------------------------------------------------- /errors/system_errors.md: -------------------------------------------------------------------------------- 1 | # 系统错误 2 | 3 | * [系统错误类](#系统错误类) 4 | - [error.errno](#errorerrno) 5 | - [error.code](#errorcode) 6 | - [error.syscall](#errorsyscall) 7 | * [通用的系统错误](#通用的系统错误) 8 | 9 | -------------------------------------------------- 10 | 11 | 12 | 当程序在运行时环境中发生异常时会产生系统错误。通常,这些是当应用违反操作系统约束(例如尝试读取不存在的文件或当用户没有足够的权限)时发生的操作错误。 13 | 14 | 系统错误通常是在系统调用(syscall)级别产生:通过在大多数 Unix 上运行 `man 2 intro` 或 `man 3 errno` 或[在线](http://man7.org/linux/man-pages/man3/errno.3.html)查找,可以获取错误代码及其含义的详尽列表。 15 | 16 | 在 Node.js 中,系统错误表现为添加额外属性的增强型 `Error` 对象。 17 | 18 | 19 | ## 系统错误类 20 | 21 | 22 | ### error.errno 23 | 24 | 返回表示**否定**错误码相应的数字,可能引用自 `man 2 intro`。例如,`ENOENT` 错误的 `errno` 的值为 `-2`,因为 `ENOENT` 的错误码为 `2`。 25 | 26 | 27 | ### error.code 28 | 29 | 返回一个表示错误码的字符串,它总是 `E` 后面跟着一串大写字母,并可能引用自 `man 2 intro`。 30 | 31 | 32 | ### error.syscall 33 | 34 | 返回描述失败的系统调用([syscall](http://man7.org/linux/man-pages/man2/syscall.2.html))的字符串。 35 | 36 | 37 | ## 通用的系统错误 38 | 39 | 这个列表并**不详尽**,但列举了开发 Node.js 程序时可能遇到的许多常见的系统错误。在[这里](http://man7.org/linux/man-pages/man3/errno.3.html)可以找到一个详尽的列表。 40 | 41 | * `EACCES`(没有权限):试图在一个文件权限不允许的文件夹中访问一个文件。 42 | 43 | * `EADDRINUSE`(地址已被使用):试图将一个服务器([net](../net/)、[http](../http/) 或 [https](../https/))绑定本地地址失败,原因是本地系统上的另一个服务已占用了该地址。 44 | 45 | * `ECONNREFUSED`(连接被拒绝):目标机器积极拒绝导致的无法连接。这通常是试图连接到国外主机上不活动的服务后的结果。 46 | 47 | * `ECONNRESET`(连接被对方重置):一个连接被对方强行关闭。这通常是因超时或自动重启导致的远程套接字(socket)丢失的结果。在 [http](../http/) 和 [net](../net/) 模块中经常会碰到。 48 | 49 | * `EEXIST`(文件已存在):一个要求目标不存在的文件操作的目标是一个已存在的文件。 50 | 51 | * `EISDIR`(是一个目录):一个对文件的操作,但给定的路径是一个目录。 52 | 53 | * `EMFILE`(在系统中打开了过多的文件):已达到系统中[文件描述符](https://en.wikipedia.org/wiki/File_descriptor)允许的最大数量,并且另外一个描述符的请求在至少关闭其中一个之前不能被满足。这在一次并行打开多个文件时会遇到,尤其是在那些在进程中限制了一个较低的文件描述符数量的操作系统上(在 particular 和 OS X 中)。为了破除这个限制,请在与运行 Node.js 进程的同一 `shell` 中运行 `ulimit -n 2048` 。 54 | 55 | * `ENOENT`(无此文件或目录):通常是由[文件操作](../fs/)引起的,这表明指定的路径组合不存在——在给定的路径上无法找到任何实体(文件或目录)。 56 | 57 | * `ENOTDIR`(不是一个目录):给定的路径组合存在,但不是所期望的目录。通常是由 [fs.readdir](../fs/fs.md#readdir) 引起的。 58 | 59 | * `ENOTEMPTY`(目录非空):一个需要空目录操作的目标目录是一个实体。通常是由 [fs.unlink](../fs/fs.md#unlink) 引起的。 60 | 61 | * `EPERM`(操作不被允许):试图执行需要提升权限的操作。 62 | 63 | * `EPIPE`(管道损坏):没有进程读取数据时写入 `pipe`、`socket` 或 `FIFO`。在 [net](../net/) 和[http](../http/) 层经常遇到,表明在远端的流(stream)准备写入前被关闭。 64 | 65 | * `ETIMEDOUT`(操作超时):由于连接方在一段时间后并没有做出合适的响应导致的连接或发送的请求失败。在 [http](../http/) 或 [net](../net/) 中经常遇到——往往标志着 `socket.end()` 没有被合适的调用。 -------------------------------------------------------------------------------- /querystring/querystring.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [querystring.stringify(obj[, sep][, eq][, options])](#stringify) 4 | * [querystring.parse(str[, sep][, eq][, options])](#parse) 5 | * [querystring.escape](#escape) 6 | * [querystring.unescape](#unescape) 7 | 8 | -------------------------------------------------- 9 | 10 | 11 |
12 | ## querystring.stringify(obj[, sep][, eq][, options]) 13 | 14 | 序列化一个对象到一个查询字符串。可以选择是否覆盖默认的分割符(`'&'`)和分配符(`'='`)。 15 | 16 | Options 对象可能包含 `encodeURIComponent` 属性(默认为 `querystring.escape`)。在有必要时,它可以用 `non-utf8` 码来编码字符串。 17 | 18 | 例子: 19 | 20 | ```javascript 21 | querystring.stringify({ 22 | foo: 'bar', 23 | baz: ['qux', 'quux'], 24 | corge: '' 25 | }) 26 | // returns 'foo=bar&baz=qux&baz=quux&corge=' 27 | 28 | querystring.stringify({ 29 | foo: 'bar', 30 | baz: 'qux' 31 | }, ';', ':') 32 | // returns 'foo:bar;baz:qux' 33 | 34 | // Suppose gbkEncodeURIComponent function already exists, 35 | // it can encode string with `gbk` encoding 36 | querystring.stringify({ 37 | w: '中文', 38 | foo: 'bar' 39 | }, null, null, { 40 | encodeURIComponent: gbkEncodeURIComponent 41 | }) 42 | // returns 'w=%D6%D0%CE%C4&foo=bar' 43 | ``` 44 | 45 | 46 |
47 | ## querystring.parse(str[, sep][, eq][, options]) 48 | 49 | 将一个查询字符串反序列化为一个对象。可以选择是否覆盖默认的分割符(`'&'`)和分配符(`'='`)。 50 | 51 | Options 对象可能包含 `maxKeys` 属性(默认为 1000),它会被用来限制已处理键(key)的数量。设为 0 可以去除键(key)的数量限制。 52 | 53 | Options 对象可能包含 `decodeURIComponent` 属性(默认为 `querystring.unescape`)。在有必要时,它可以将 `non-utf8` 码解码为字符串。 54 | 55 | ```javascript 56 | querystring.parse('foo=bar&baz=qux&baz=quux&corge') 57 | // returns { foo: 'bar', baz: ['qux', 'quux'], corge: '' } 58 | 59 | // Suppose gbkDecodeURIComponent function already exists, 60 | // it can decode `gbk` encoding string 61 | querystring.parse('w=%D6%D0%CE%C4&foo=bar', null, null, 62 | { decodeURIComponent: gbkDecodeURIComponent }) 63 | // returns { w: '中文', foo: 'bar' } 64 | ``` 65 | 66 | 67 |
68 | ## querystring.escape 69 | 70 | 供 `querystring.stringify` 使用的转意函数,在必要的时候可被重写。 71 | 72 | 73 |
74 | ## querystring.unescape 75 | 76 | 供 `querystring.parse` 使用的反转意函数,在必要的时候可被重写。 77 | 78 | 它会首先尝试使用 `encodeURIComponent`,但如果失败,它会回滚到一个安全的等效结果上,在处理畸形的 URL 时也不会抛出错误。 -------------------------------------------------------------------------------- /cli/options.md: -------------------------------------------------------------------------------- 1 | # 选项(Options) 2 | 3 | * [-v, --version](#v-version) 4 | * [-h, --help](#h-help) 5 | * [-e, --eval "script"](#e-eval-script) 6 | * [-p, --print "script"](#p-print-script) 7 | * [-c, --check](#c-check) 8 | * [-i, --interactive](#i-interactive) 9 | * [-r, --require module](#r-require-module) 10 | * [--no-deprecation](#nodeprecation) 11 | * [--trace-deprecation](#tracedeprecation) 12 | * [--throw-deprecation](#throwdeprecation) 13 | * [--trace-sync-io](#tracesyncio) 14 | * [--zero-fill-buffers](#zerofillbuffers) 15 | * [--track-heap-objects](#trackheapobjects) 16 | * [--prof-process](#profprocess) 17 | * [--v8-options](#v8options) 18 | * [--tls-cipher-list=list](#tlscipherlistlist) 19 | * [--enable-fips](#enablefips) 20 | * [--force-fips](#forcefips) 21 | * [--icu-data-dir=file](#icudatadirfile) 22 | 23 | ---------------------------------------- 24 | 25 | 26 | ## -v, --version 27 | 28 | 打印 Node.js 的版本号。 29 | 30 | 31 | ## -h, --help 32 | 33 | 打印 Node.js 的命令行选项。此选项的输出不如本文档详细。 34 | 35 | 36 | ## -e, --eval "script" 37 | 38 | 将以下参数作为 JavaScript 进行评估。在 REPL 中预定义的模块也可以在 `script` 中使用。 39 | 40 | 41 | ## -p, --print "script" 42 | 43 | 与 `-e` 相同,但会打印结果。 44 | 45 | 46 | ## -c, --check 47 | 48 | 在不执行的情况下,对脚本进行语法检查。 49 | 50 | 51 | ## -i, --interactive 52 | 53 | 打开 REPL,即便 stdin 看起来不像终端。 54 | 55 | 56 | ## -r, --require module 57 | 58 | 在启动时预加载指定的模块。 59 | 60 | 遵循 `require()` 的模块解析规则。`module` 可以是文件的路径,也可以是 Node.js 的模块名称。 61 | 62 | 63 | ## --no-deprecation 64 | 65 | 静默废弃的警告。 66 | 67 | 68 | ## --trace-deprecation 69 | 70 | 打印废弃的堆栈跟踪。 71 | 72 | 73 | ## --throw-deprecation 74 | 75 | 抛出废弃的错误。 76 | 77 | 78 | ## --trace-sync-io 79 | 80 | 每当在事件循环的第一帧之后检测到同步 I/O 时,打印堆栈跟踪。 81 | 82 | 83 | ## --zero-fill-buffers 84 | 85 | 自动填充所有新分配的 [Buffer](../buffer/class_Buffer.md#) 和 [SlowBuffer](../buffer/class_SlowBuffer.md#) 实例。 86 | 87 | 88 | ## --track-heap-objects 89 | 90 | 为堆快照分配的堆栈对象。 91 | 92 | 93 | ## --prof-process 94 | 95 | 使用 v8 选项 `--prof` 处理 v8 分析器生成的输出。 96 | 97 | 98 | ## --v8-options 99 | 100 | 打印 v8 命令行选项。 101 | 102 | 103 | ## --tls-cipher-list=list 104 | 105 | 指定备用的默认 TLS 加密列表。(需要使用支持的加密构建 Node.js 。(默认)) 106 | 107 | 108 | ## --enable-fips 109 | 110 | 启动时启用符合 FIPS 标准的加密。(需要使用 `./configure --openssl-fips` 构建 Node.js。) 111 | 112 | 113 | ## --icu-data-dir=file 114 | 115 | 指定 ICU 数据的加载路径。(覆盖 NODE_ICU_DATA) -------------------------------------------------------------------------------- /repl/class_REPLServer.md: -------------------------------------------------------------------------------- 1 | # REPLServer类 2 | 3 | * ['reset' 事件](#reset-事件) 4 | * ['exit' 事件](#exit-事件) 5 | * [replServer.defineCommand(keyword, cmd)](#replserverdefinecommandkeyword-cmd) 6 | * [replServer.displayPrompt([preserveCursor])](#replserverdisplaypromptpreservecursor) 7 | 8 | -------------------------------------------------- 9 | 10 | 它继承自 [Readline Interface](../readline/class_Interface.md#) 并带有以下事件: 11 | 12 | 13 | ## 'reset' 事件 14 | 15 | `function (context) {}` 16 | 17 | 当 REPL 的上下文被重置时发出。这在你键入 `.clear` 时发生。如果你启动时带有 `{ useGlobal: true }`,那么这个事件永远不会被触发。 18 | 19 | 监听 `'reset'` 事件的例子: 20 | 21 | ``` javascript 22 | // Extend the initial repl context. 23 | var replServer = repl.start({ 24 | options... 25 | }); 26 | someExtension.extend(r.context); 27 | 28 | // When a new context is created extend it as well. 29 | replServer.on('reset', (context) => { 30 | console.log('repl has a new context'); 31 | someExtension.extend(context); 32 | }); 33 | ``` 34 | 35 | 36 | ## 'exit' 事件 37 | 38 | `function () {}` 39 | 40 | 当用户以任何定义的方式退出 REPL 时发出。也就是说,在 repl 中键入 `.exit`,按下 `Ctrl+C` 两次来示意 `SIGINT`,或在 `input` 流中,按下 `Ctrl+D` 来示意 `'end'`。 41 | 42 | 监听 `'exit'` 事件的例子: 43 | 44 | ``` javascript 45 | replServer.on('exit', () => { 46 | console.log('Got "exit" event from repl!'); 47 | process.exit(); 48 | }); 49 | ``` 50 | 51 | 52 | ## replServer.defineCommand(keyword, cmd) 53 | 54 | * `keyword` {String} 55 | 56 | * `cmd` {Object} | {Function} 57 | 58 | 使一个命令在 REPL 中可用。该命令通过键入 `.` 后面跟着关键字来调用。该 `cmd` 是一个具有以下值的对象: 59 | 60 | * `help` - 当输入 `.help` 时显示的帮助文本信息(可选)。 61 | 62 | * `action` - 一个要执行的函数,可能可以接受字符串参数,当调用命令时,绑定到 REPL 服务器实例上(必需)。 63 | 64 | 如果提供了一个函数而不是一个 `cmd` 对象,它被视为 `action`。 65 | 66 | 定义命令的例子: 67 | 68 | ``` javascript 69 | // repl_test.js 70 | const repl = require('repl'); 71 | 72 | var replServer = repl.start(); 73 | replServer.defineCommand('sayhello', { 74 | help: 'Say hello', 75 | action: function (name) { 76 | this.write(`Hello, ${name}!\n`); 77 | this.displayPrompt(); 78 | } 79 | }); 80 | ``` 81 | 82 | 从 REPL 中调用该命令的例子: 83 | 84 | ``` bash 85 | > .sayhello Node.js User 86 | Hello, Node.js User! 87 | ``` 88 | 89 | 90 | ## replServer.displayPrompt([preserveCursor]) 91 | 92 | * `preserveCursor` {Boolean} 93 | 94 | 像 [readline.prompt](../readline/class_Interface.md#rlpromptpreservecursor) 那样,当在块内时,添加缩进和省略号。`preserveCursor` 参数是传给 [readline.prompt](../readline/class_Interface.md#rlpromptpreservecursor) 的。这主要用于 `defineCommand`。它也用于内部渲染每个提示行。 -------------------------------------------------------------------------------- /timers/timer.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [setTimeout(callback, delay[, arg][, ...])](#setTimeout) 4 | * [clearTimeout(timeoutObject)](#clearTimeout) 5 | * [setInterval(callback, delay[, arg][, ...])](#setInterval) 6 | * [clearInterval(intervalObject)](#clearInterval) 7 | * [setImmediate(callback[, arg][, ...])](#setImmediate) 8 | * [clearImmediate(immediateObject)](#clearImmediate) 9 | * [ref()](#ref) 10 | * [unref()](#unref) 11 | 12 | -------------------------------------------------- 13 | 14 | 15 |
16 | ## setTimeout(callback, delay[, arg][, ...]) 17 | 18 | 在 `delay` 毫秒后执行一次回调函数 `callback` 。返回一个可能被 [clearTimeout](#clearTimeout) 用到的 `timeoutObject` 。其他可选参数可以传递给回调函数。 19 | 20 | 请务必注意,您的回调有可能不会在准确的 `delay` 毫秒后被调用。Node.js 不保证回调被触发的精确时间和顺序。回调会在尽可能接近所指定的时间上被调用。 21 | 22 | 根据浏览器默认行为,当你使用大于 2147483647 毫秒(约25天)或小于 1 毫秒的延迟时,`delay` 会被设置为 1 ,超时将立即执行。 23 | 24 | 25 |
26 | ## clearTimeout(timeoutObject) 27 | 28 | 阻止一个由 [setTimeout](#setTimeout) 创建的 `timeoutObject` 触发。 29 | 30 | 31 |
32 | ## setInterval(callback, delay[, arg][, ...]) 33 | 34 | 每隔 `delay` 毫秒执行一次回调函数 `callback` 。返回一个可能被 [clearInterval](#clearInterval) 用到的 `intervalObject` 。其他可选参数可以传递给回调函数。 35 | 36 | 根据浏览器默认行为,当你使用大于 2147483647 毫秒(约25天)或小于 1 毫秒的延迟时,Node.js将使用 1 作为延迟。 37 | 38 | 39 |
40 | ## clearInterval(intervalObject) 41 | 42 | 阻止一个由 [setInterval](#setInterval) 创建的 `intervalObject` 触发。 43 | 44 | 45 |
46 | ## setImmediate(callback[, arg][, ...]) 47 | 48 | 在 I/O 事件回调之后以及 [setTimeout](#setTimeout) 和 [setInterval](#setInterval) 之前“立即”执行 `callback` 。返回一个可能被 [clearImmediate](#clearImmediate) 用到的 `immediateObject` 。其他可选参数可以传递给回调函数。 49 | 50 | 51 |
52 | ## clearImmediate(immediateObject) 53 | 54 | 阻止一个由 [setImmediate](#setImmediate) 创建的 `immediateObject` 触发。 55 | 56 | 57 |
58 | ## ref() 59 | 60 | 如果您之前 `unref()` 了一个定时器,您可以调用 `ref()` 来明确要求定时器让程序保持运行。如果定时器已被 `ref` 那么再次调用 `ref` 不会产生其它影响。 61 | 62 | 返回定时器对象。 63 | 64 | 65 |
66 | ## unref() 67 | 68 | [setTimeout](#setTimeout) 和 [setInterval](#setInterval) 所返回的值都包含 `timer.unref()` 方法,该方法允许您创建一个活动的但当它是事件循环中仅剩的项目时不会保持程序运行的定时器。如果定时器已被 `unref` ,再次调用 `unref` 不会产生其它影响。 69 | 70 | 在使用 [setTimeout](#setTimeout) 的情况下,`unref` 会创建另一个独立的定时器,并唤醒事件循环。创建太多这种定时器可能会影响事件循环的性能,**慎用**。 71 | 72 | 返回定时器对象。 -------------------------------------------------------------------------------- /v8/v8.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [setFlagsFromString(string)](#setFlagsFromString) 4 | * [getHeapStatistics()](#getHeapStatistics) 5 | * [getHeapSpaceStatistics()](#getHeapSpaceStatistics) 6 | 7 | -------------------------------------------------- 8 | 9 | 10 |
11 | ## setFlagsFromString(string) 12 | 13 | 设置额外的 V8 命令行标志。请谨慎使用;在虚拟机已经开始后更改设置,可能会导致不可预知的行为,包括崩溃和数据丢失。或者,它可能什么也不做。 14 | 15 | 一个 Node.js 版本可用的 v8 选项可以通过 `node --v8-options` 确定。一个非官方的社区维护可选列表及其影响可以在 [这里](https://github.com/thlorenz/v8-flags/blob/master/flags-0.11.md) 找到。 16 | 17 | 用法: 18 | 19 | ```javascript 20 | // Print GC events to stdout for one minute. 21 | const v8 = require('v8'); 22 | v8.setFlagsFromString('--trace_gc'); 23 | setTimeout(function() { v8.setFlagsFromString('--notrace_gc'); }, 60e3); 24 | ``` 25 | 26 | 27 |
28 | ## getHeapStatistics() 29 | 30 | 返回一个具有以下属性的对象: 31 | 32 | ```javascript 33 | { 34 | total_heap_size: 7326976, 35 | total_heap_size_executable: 4194304, 36 | total_physical_size: 7326976, 37 | total_available_size: 1152656, 38 | used_heap_size: 3476208, 39 | heap_size_limit: 1535115264 40 | } 41 | ``` 42 | 43 | 44 |
45 | ## getHeapSpaceStatistics() 46 | 47 | 返回关于 V8 堆空间的统计,如,构成 v8 堆的片段。堆空间的秩序而不是堆空间的可用性,可以通过 V8 `GetHeapSpaceStatistics` 函数提供的统计得到保证。 48 | 49 | 结果举例: 50 | 51 | ```javascript 52 | [ 53 | { 54 | "space_name": "new_space", 55 | "space_size": 2063872, 56 | "space_used_size": 951112, 57 | "space_available_size": 80824, 58 | "physical_space_size": 2063872 59 | }, 60 | { 61 | "space_name": "old_space", 62 | "space_size": 3090560, 63 | "space_used_size": 2493792, 64 | "space_available_size": 0, 65 | "physical_space_size": 3090560 66 | }, 67 | { 68 | "space_name": "code_space", 69 | "space_size": 1260160, 70 | "space_used_size": 644256, 71 | "space_available_size": 960, 72 | "physical_space_size": 1260160 73 | }, 74 | { 75 | "space_name": "map_space", 76 | "space_size": 1094160, 77 | "space_used_size": 201608, 78 | "space_available_size": 0, 79 | "physical_space_size": 1094160 80 | }, 81 | { 82 | "space_name": "large_object_space", 83 | "space_size": 0, 84 | "space_used_size": 0, 85 | "space_available_size": 1490980608, 86 | "physical_space_size": 0 87 | } 88 | ] 89 | ``` 90 | -------------------------------------------------------------------------------- /punycode/punycode.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | #### 属性 4 | 5 | * [punycode.version](#version) 6 | * [punycode.ucs2](#ucs2) 7 | - [punycode.ucs2.encode(codePoints)](#ucs2_encode) 8 | - [punycode.ucs2.decode(string)](#ucs2_decode) 9 | 10 | #### 方法 11 | 12 | * [punycode.encode(string)](#encode) 13 | * [punycode.decode(string)](#decode) 14 | * [punycode.toUnicode(domain)](#toUnicode) 15 | * [punycode.toASCII(domain)](#toASCII) 16 | 17 | -------------------------------------------------- 18 | 19 | 20 |
21 | ## punycode.version 22 | 23 | 一个代表当前 Punycode.js 版本号的字符串。 24 | 25 | 26 |
27 | ## punycode.ucs2 28 | 29 | 30 |
31 | #### punycode.ucs2.encode(codePoints) 32 | 33 | 创建一个包含字符串中每个 Unicode 符号的数字编码点的数组。由于 [JavaScript 在内部使用 UCS-2](https://mathiasbynens.be/notes/javascript-encoding), 该函数会匹配 UTF-16 将一对替代半部(UCS-2 暴露的单独的字符)转换为单个编码点。 34 | 35 | ```javascript 36 | punycode.ucs2.decode('abc'); // [0x61, 0x62, 0x63] 37 | // surrogate pair for U+1D306 tetragram for centre: 38 | punycode.ucs2.decode('\uD834\uDF06'); // [0x1D306] 39 | ``` 40 | 41 | 42 |
43 | #### punycode.ucs2.decode(string) 44 | 45 | 根据一组数字编码点值创建一个字符串。 46 | 47 | ```javascript 48 | punycode.ucs2.encode([0x61, 0x62, 0x63]); // 'abc' 49 | punycode.ucs2.encode([0x1D306]); // '\uD834\uDF06' 50 | ``` 51 | 52 | 53 |
54 | ## punycode.encode(string) 55 | 56 | 将一个 Unicode 符号的字符串转换为纯 ASCII 符号的 Punycode 字符串。 57 | 58 | ```javascript 59 | // encode domain name parts 60 | punycode.encode('mañana'); // 'maana-pta' 61 | punycode.encode('☃-⌘'); // '--dqo34k' 62 | ``` 63 | 64 | 65 |
66 | ## punycode.decode(string) 67 | 68 | 将一个纯 ASCII 符号的 Punycode 字符串转换为 Unicode 符号的字符串。 69 | 70 | ```javascript 71 | // decode domain name parts 72 | punycode.decode('maana-pta'); // 'mañana' 73 | punycode.decode('--dqo34k'); // '☃-⌘' 74 | ``` 75 | 76 | 77 |
78 | ## punycode.toUnicode(domain) 79 | 80 | 将一个表示域名的 Punycode 字符串转换为 Unicode。只有域名中的 Punycode 部分会转换,也就是说你在一个已经转换为 Unicode 的字符串上调用它也是没问题的。 81 | 82 | ```javascript 83 | // decode domain names 84 | punycode.toUnicode('xn--maana-pta.com'); // 'mañana.com' 85 | punycode.toUnicode('xn----dqo34k.com'); // '☃-⌘.com' 86 | ``` 87 | 88 | 89 |
90 | ## punycode.toASCII(domain) 91 | 92 | 将一个表示域名的 Unicode 字符串转换为 Punycode。只有域名的非 ASCII 部分会被转换,也就是说你在一个已经是 ASCII 的域名上调用它也是没问题的。 93 | 94 | ```javascript 95 | // encode domain names 96 | punycode.toASCII('mañana.com'); // 'xn--maana-pta.com' 97 | punycode.toASCII('☃-⌘.com'); // 'xn----dqo34k.com' 98 | ``` -------------------------------------------------------------------------------- /repl/repl.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [repl.start([options])](#replstartoptions) 4 | 5 | -------------------------------------------------- 6 | 7 | ## repl.start([options]) 8 | 9 | 返回并启动一个 `REPLServer` 实例,继承自 [Readline Interface](../readline/class_Interface.md#)。接受具有以下值的“options”对象: 10 | 11 | * `prompt` - 用于所有 I/O `stream` 的提示。默认为 `> `。 12 | 13 | * `input` - 要监听的可读流。默认为 `process.stdin`。 14 | 15 | * `output` - 写入逐行读取数据的写入流。默认为 `process.stdout`。 16 | 17 | * `terminal` - 如果 `stream` 应该像一个 `TTY` 对待时,传入 `true`,并写入 ANSI/VT100 转义码。默认在 `output` 流实例化时检测 `isTTY`。 18 | 19 | * `eval` - 将用于评估每个给定的行的函数。默认 `eval()` 为异步封装器。参见下面的自定义示例 `eval`。 20 | 21 | * `useColors` - 指定 `writer` 函数是否应该输出颜色的布尔值。如果设置了一个不同的 `writer` 函数,那么这将没有效果。默认为该 repl 的 `terminal` 值。 22 | 23 | * `useGlobal` - 如果设置为 `true`,那么该 repl 会使用 `global` 对象,代替在单独上下文中运行脚本。默认为 `false`。 24 | 25 | * `ignoreUndefined` - 如果设置为 `true`,那么 repl 将不会输出返回值为 `undefined` 的命令。默认为 `false`。 26 | 27 | * `writer` - 为每个命令调用的函数,它返回格式化后(包括着色)的显示。默认为 `util.inspect`。 28 | 29 | * `replMode` - 控制 repl 是否以严格模式,默认模式或混合模式(“魔术”模式)运行所有命令。可接受的值为: 30 | 31 | - `repl.REPL_MODE_SLOPPY` - 以粗略模式运行命令。 32 | 33 | - `repl.REPL_MODE_STRICT` - 以严格模式运行命令。这相当于在每个 repl 语句前面带上 `'use strict'`。 34 | 35 | - `repl.REPL_MODE_MAGIC` - 尝试在默认模式下运行命令。如果他们无法解析,请在严格模式下重试。 36 | 37 | 如果有以下签名的情况下,你可以使用你自己的 `eval` 函数: 38 | 39 | ``` javascript 40 | function eval(cmd, context, filename, callback) { 41 | callback(null, result); 42 | } 43 | ``` 44 | 45 | 选项卡完成时,`eval` 将用 `.scope` 作为输入字符串调用。它期望返回用于自动补全的作用域名称的数组。 46 | 47 | 多数的 REPLs 可以针对相同的 Node.js 运行实例启动。每个将共享相同的全局对象,但会具有唯一的 I/O。 48 | 49 | 这里有一个在 stdin、Unix 套接字和 TCP 套接字上运行 REPL 的例子: 50 | 51 | ``` javascript 52 | const net = require('net'); 53 | const repl = require('repl'); 54 | var connections = 0; 55 | 56 | repl.start({ 57 | prompt: 'Node.js via stdin> ', 58 | input: process.stdin, 59 | output: process.stdout 60 | }); 61 | 62 | net.createServer((socket) => { 63 | connections += 1; 64 | repl.start({ 65 | prompt: 'Node.js via Unix socket> ', 66 | input: socket, 67 | output: socket 68 | }).on('exit', () => { 69 | socket.end(); 70 | }) 71 | }).listen('/tmp/node-repl-sock'); 72 | 73 | net.createServer((socket) => { 74 | connections += 1; 75 | repl.start({ 76 | prompt: 'Node.js via TCP socket> ', 77 | input: socket, 78 | output: socket 79 | }).on('exit', () => { 80 | socket.end(); 81 | }); 82 | }).listen(5001); 83 | ``` 84 | 85 | 在一个命令行中运行这个程序会在 stdin 中启动一个 REPL。其他的 REPL 客户端,可以通过 Unix 套接字或 TCP 套接字进行连接。`telnet` 对于连接到 TCP 套接字很有用,`socat` 可以用于连接到 Unix 和 TCP 套接字。 86 | 87 | 通过从基于 Unix 套接字的服务器而不是从 stdin 启动 REPL,你可以连接到长期运行的 Node.js 进程,而无需重新启动它。 88 | 89 | 在一个 `net.Server` 和 `net.Socket` 的实例上运行“全功能”(`terminal`)REPL 的例子,详见:[https://gist.github.com/2209310](https://gist.github.com/2209310)。 90 | 91 | 在 `curl(1)` 上运行 REPL 实例的例子,详见:[https://gist.github.com/2053342](https://gist.github.com/2053342) -------------------------------------------------------------------------------- /crypto/class_Sign.md: -------------------------------------------------------------------------------- 1 | # Sign类 2 | 3 | * [sign.update(data[, input_encoding])](#signupdatedata-inputencoding) 4 | * [sign.sign(private_key[, output_format])](#signsignprivatekey-outputformat) 5 | 6 | -------------------------------------------------- 7 | 8 | `Sign` 类是用于生成签名的工具类。它可以以两种方式之一使用: 9 | 10 | * 作为一个可写[流](../stream/),写入要签名的数据,[sign.sign()](#signsignprivatekey-outputformat) 用于生成和返回签名。 11 | 12 | * 使用 [sign.update()](#signupdatedata-inputencoding) 和 [sign.sign()](#signsignprivatekey-outputformat) 方法来产生签名。 13 | 14 | [crypto.createSign()](./crypto.md#cryptocreatesignalgorithm) 方法用于创建 `Sign` 实例。`Sign` 对象无法直接使用 `new` 关键词创建。 15 | 16 | 示例:将 `Sign` 对象用作流: 17 | 18 | ``` javascript 19 | const crypto = require('crypto'); 20 | const sign = crypto.createSign('RSA-SHA256'); 21 | 22 | sign.write('some data to sign'); 23 | sign.end(); 24 | 25 | const private_key = getPrivateKeySomehow(); 26 | console.log(sign.sign(private_key, 'hex')); 27 | // Prints the calculated signature 28 | ``` 29 | 30 | 示例:使用 [sign.update()](#signupdatedata-inputencoding) 和 [sign.sign()](#signsignprivatekey-outputformat) 方法: 31 | 32 | ``` javascript 33 | const crypto = require('crypto'); 34 | const sign = crypto.createSign('RSA-SHA256'); 35 | 36 | sign.update('some data to sign'); 37 | 38 | const private_key = getPrivateKeySomehow(); 39 | console.log(sign.sign(private_key, 'hex')); 40 | // Prints the calculated signature 41 | ``` 42 | 43 | `sign` 实例也可以通过传入摘要算法名称来创建,在这种情况下 OpenSSL 将从 PEM 格式的私钥类型推断完全的签名算法,包括没有直接暴露名称常量的算法,如,`'ecdsa-with-SHA256'`。 44 | 45 | 示例:使用 SHA256 的 ECDSA 签名: 46 | 47 | ``` javascript 48 | const crypto = require('crypto'); 49 | const sign = crypto.createSign('sha256'); 50 | 51 | sign.update('some data to sign'); 52 | 53 | const private_key = '-----BEGIN EC PRIVATE KEY-----\n' + 54 | 'MHcCAQEEIF+jnWY1D5kbVYDNvxxo/Y+ku2uJPDwS0r/VuPZQrjjVoAoGCCqGSM49\n' + 55 | 'AwEHoUQDQgAEurOxfSxmqIRYzJVagdZfMMSjRNNhB8i3mXyIMq704m2m52FdfKZ2\n' + 56 | 'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' + 57 | '-----END EC PRIVATE KEY-----\n'; 58 | 59 | console.log(sign.sign(private_key).toString('hex')); 60 | ``` 61 | 62 | 63 | ## sign.update(data[, input_encoding]) 64 | 65 | 用给定的 `data` 更新 `Sign` 内容,给出的 `input_encoding` 编码,可以是 `'utf8'`、`'ascii'` 或 `'binary'`。如果没有提供 `encoding`,同时 `data` 是一个字符串,将强制使用 `'utf8'` 编码。如果 `data` 是一个 [Buffer](../buffer/),那么 `input_encoding` 参数会被忽略。 66 | 67 | 当它作为流时,可以在新数据上多次调用。 68 | 69 | 70 | ## sign.sign(private_key[, output_format]) 71 | 72 | 使用 [sign.update()](#signupdatedata-inputencoding) 或 [sign.write()](../stream/api_for_stream_consumers.md#write) 计算所有传递的数据的签名。 73 | 74 | `private_key` 参数可以是一个对象或字符串。如果 `private_key` 是一个字符串,它被视为没有密码的原始密钥。如果 `private_key` 是一个对象,它被解释为包含两个属性的哈希: 75 | 76 | * `key`:{String} - PEM 编码的私钥 77 | 78 | * `passphrase`:{String} - 私钥的密码 79 | 80 | `output_format` 可以指定为 `'binary'`、`'hex'` 或 `'base64'` 中的一种。如果提供了 `output_format` 则返回一个字符串;否则返回一个 [Buffer](../buffer/)。 81 | 82 | 在调用 `sign.sign()` 方法之后,`Sign` 对象将不能再次使用。多次调用将导致抛出错误。 -------------------------------------------------------------------------------- /modules/module.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [module.id](#moduleid) 4 | * [module.filename](#modulefilename) 5 | * [module.loaded](#moduleloaded) 6 | * [module.parent](#moduleparent) 7 | * [module.children](#modulechildren) 8 | * [module.exports](#moduleexports) 9 | - [exports 的别名](#exports-的别名) 10 | * [module.require(id)](#modulerequireid) 11 | 12 | -------------------------------------------------- 13 | 14 | ## module 对象 15 | 16 | 添加:v0.1.16 17 | 18 | - {Object} 19 | 20 | 在每一个模块中,自由变量 `module` 是对表示当前模块的对象的引用。为了方便起见,`module.exports` 也可以通过模块全局的 `exports` 对象访问到。`module` 实际上不是全局的,而是每个模块内部的。 21 | 22 | 23 | ## module.id 24 | 25 | 添加:v0.1.16 26 | 27 | - {String} 28 | 29 | 模块的标识符。通常是完全解析后的文件名。 30 | 31 | 32 | ## module.filename 33 | 34 | 添加:v0.1.16 35 | 36 | - {String} 37 | 38 | 模块完全解析后的文件名。 39 | 40 | 41 | ## module.loaded 42 | 43 | 添加:v0.1.16 44 | 45 | - {Boolean} 46 | 47 | 显示模块是否已经加载完成,或正在加载中。 48 | 49 | 50 | ## module.parent 51 | 52 | 添加:v0.1.16 53 | 54 | - {Object} Module 对象 55 | 56 | 在模块中最先引入的模块。 57 | 58 | 59 | ## module.children 60 | 61 | 添加:v0.1.16 62 | 63 | - {Array} 64 | 65 | 需要引入该模块的模块对象。 66 | 67 | 68 | ## module.exports 69 | 70 | 添加:v0.1.16 71 | 72 | - {Object} 73 | 74 | `module.exports` 对象由模块系统创建。有时候这是难以接受的,许多人都希望他们的模块成为某个类的实例。为了实现这一点,你需要将要导出的对象赋值给 `module.exports`。需要注意的是如果你将需要导出的对象赋值给 `exports` 只会简单的绑定到本地变量 `exports` 上,这很可能不是你想要的结果。 75 | 76 | 例如,假设我们创建了一个名为 `a.js` 模块: 77 | 78 | ``` javascript 79 | const EventEmitter = require('events'); 80 | 81 | module.exports = new EventEmitter(); 82 | 83 | // 处理一些工作,并在一段时间后从模块自身内部发出 'ready' 事件。 84 | setTimeout(() => { 85 | module.exports.emit('ready'); 86 | }, 1000); 87 | ``` 88 | 89 | 然后,在另一个文件中我们可以这么做: 90 | 91 | ``` javascript 92 | const a = require('./a'); 93 | a.on('ready', () => { 94 | console.log('module a is ready'); 95 | }); 96 | ``` 97 | 98 | 注意,必须立即完成对 `module.expors` 的赋值,而不能在任何回调中完成。这样是不起作用的: 99 | 100 | x.js: 101 | 102 | ``` javascript 103 | setTimeout(() => { 104 | module.exports = { a: 'hello' }; 105 | }, 0); 106 | ``` 107 | 108 | y.js: 109 | 110 | ``` javascript 111 | const x = require('./x'); 112 | console.log(x.a); 113 | ``` 114 | 115 | #### exports 的别名 116 | 117 | 添加:v0.1.16 118 | 119 | 变量 `exports` 是模块内部在最开始生成的指向 `module.exports` 的引用。对于任何变量而言,如果你为其赋一个新值,它将不再绑定到以前的值。 120 | 121 | 为了解释这个情况,我们想象以下对 `require()` 的假设: 122 | 123 | ``` javascript 124 | function require(...) { 125 | // ... 126 | ((module, exports) => { 127 | // 在这里写你的模块代码 128 | // 重新分配 export,export 不在是 module.exports 的快捷方式,并且不再导出任何内容。 129 | exports = some_func; 130 | // 使你的模块导出内容 131 | module.exports = some_func; 132 | })(module, module.exports); 133 | 134 | return module; 135 | } 136 | ``` 137 | 138 | 原则上,如果你理解不了 `exports` 和 `module.exports` 之间的关系,请忽略 `exports`,只使用 `module.exports`。 139 | 140 | 141 | ## module.require(id) 142 | 143 | 添加:v0.5.1 144 | 145 | - `id` {String} 146 | 147 | - 返回:{Object} 已解析的模块的 `module.exports` 148 | 149 | `module.require` 方法提供了一种像 `require()` 那样从原始模块加载一个模块的方式。 150 | 151 | 注意,为了做到这一点,你必须获取一个 `module` 对象的引用。因为 `require()` 会返回 `module.exports`,并且 `module` 是一个典型的*只能*在特定模块作用域内有效的变量,如果想要使用它,就必须明确的导出。 -------------------------------------------------------------------------------- /stream/simplified_constructor_api.md: -------------------------------------------------------------------------------- 1 | # 简化的构造函数API 2 | 3 | * [Readable](#Readable) 4 | * [Writable](#Writable) 5 | * [Duplex](#Duplex) 6 | * [Transform](#Transform) 7 | 8 | -------------------------------------------------- 9 | 10 | 11 | 在简单的情况下,不通过继承来构建流,现在会有一些额外的好处。 12 | 13 | 这可以通过传递适当的方法作为构造选项来实现: 14 | 15 | 例子: 16 | 17 | 18 |
19 | ## Readable 20 | 21 | ```javascript 22 | var readable = new stream.Readable({ 23 | read: function (n) { 24 | // sets this._read under the hood 25 | 26 | // push data onto the read queue, passing null 27 | // will signal the end of the stream (EOF) 28 | this.push(chunk); 29 | } 30 | }); 31 | ``` 32 | 33 | 34 |
35 | ## Writable 36 | 37 | ```javascript 38 | var writable = new stream.Writable({ 39 | write: function (chunk, encoding, next) { 40 | // sets this._write under the hood 41 | 42 | // An optional error can be passed as the first argument 43 | next() 44 | } 45 | }); 46 | 47 | // or 48 | 49 | var writable = new stream.Writable({ 50 | writev: function (chunks, next) { 51 | // sets this._writev under the hood 52 | 53 | // An optional error can be passed as the first argument 54 | next() 55 | } 56 | }); 57 | ``` 58 | 59 | 60 |
61 | ## Duplex 62 | 63 | ```javascript 64 | var duplex = new stream.Duplex({ 65 | read: function (n) { 66 | // sets this._read under the hood 67 | 68 | // push data onto the read queue, passing null 69 | // will signal the end of the stream (EOF) 70 | this.push(chunk); 71 | }, 72 | write: function (chunk, encoding, next) { 73 | // sets this._write under the hood 74 | 75 | // An optional error can be passed as the first argument 76 | next() 77 | } 78 | }); 79 | 80 | // or 81 | 82 | var duplex = new stream.Duplex({ 83 | read: function (n) { 84 | // sets this._read under the hood 85 | 86 | // push data onto the read queue, passing null 87 | // will signal the end of the stream (EOF) 88 | this.push(chunk); 89 | }, 90 | writev: function (chunks, next) { 91 | // sets this._writev under the hood 92 | 93 | // An optional error can be passed as the first argument 94 | next() 95 | } 96 | }); 97 | ``` 98 | 99 | 100 |
101 | ## Transform 102 | 103 | ```javascript 104 | var transform = new stream.Transform({ 105 | transform: function (chunk, encoding, next) { 106 | // sets this._transform under the hood 107 | 108 | // generate output as many times as needed 109 | // this.push(chunk); 110 | 111 | // call when the current chunk is consumed 112 | next(); 113 | }, 114 | flush: function (done) { 115 | // sets this._flush under the hood 116 | 117 | // generate output as many times as needed 118 | // this.push(chunk); 119 | 120 | done(); 121 | } 122 | }); 123 | ``` -------------------------------------------------------------------------------- /zlib/examples.md: -------------------------------------------------------------------------------- 1 | # 示例 2 | 3 | 压缩或解压缩一个文件可以通过导流一个 fs.ReadStream 到一个 zlib 流,然后到一个 fs.WriteStream 来完成。 4 | 5 | ```javascript 6 | const gzip = zlib.createGzip(); 7 | const fs = require('fs'); 8 | const inp = fs.createReadStream('input.txt'); 9 | const out = fs.createWriteStream('input.txt.gz'); 10 | 11 | inp.pipe(gzip).pipe(out); 12 | ``` 13 | 14 | 一步压缩或解压缩数据可以通过快捷方法来完成。 15 | 16 | ```javascript 17 | const input = '.................................'; 18 | zlib.deflate(input, (err, buffer) => { 19 | if (!err) { 20 | console.log(buffer.toString('base64')); 21 | } else { 22 | // handle error 23 | } 24 | }); 25 | 26 | const buffer = new Buffer('eJzT0yMAAGTvBe8=', 'base64'); 27 | zlib.unzip(buffer, (err, buffer) => { 28 | if (!err) { 29 | console.log(buffer.toString()); 30 | } else { 31 | // handle error 32 | } 33 | }); 34 | ``` 35 | 36 | 要在 HTTP 客户端或服务器中使用此模块,请在请求中使用 [accept-encoding](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3) 和在响应中使用 [content-encoding](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11) 头。 37 | 38 | **注意:这些例子只是极其简单地展示了基础的概念**。Zlib 编码消耗非常大,其结果应当被缓存。详见 [优化内存占用]() 中更多的关于 Zlib 用法中对速度 / 内存 / 压缩的权衡取舍。 39 | 40 | ```javascript 41 | // client request example 42 | const zlib = require('zlib'); 43 | const http = require('http'); 44 | const fs = require('fs'); 45 | const request = http.get({ 46 | host: 'izs.me', 47 | path: '/', 48 | port: 80, 49 | headers: { 50 | 'accept-encoding': 'gzip,deflate' 51 | } 52 | }); 53 | request.on('response', (response) => { 54 | var output = fs.createWriteStream('izs.me_index.html'); 55 | 56 | switch (response.headers['content-encoding']) { 57 | // or, just use zlib.createUnzip() to handle both cases 58 | case 'gzip': 59 | response.pipe(zlib.createGunzip()).pipe(output); 60 | break; 61 | case 'deflate': 62 | response.pipe(zlib.createInflate()).pipe(output); 63 | break; 64 | default: 65 | response.pipe(output); 66 | break; 67 | } 68 | }); 69 | 70 | // server example 71 | // Running a gzip operation on every request is quite expensive. 72 | // It would be much more efficient to cache the compressed buffer. 73 | const zlib = require('zlib'); 74 | const http = require('http'); 75 | const fs = require('fs'); 76 | http.createServer((request, response) => { 77 | var raw = fs.createReadStream('index.html'); 78 | var acceptEncoding = request.headers['accept-encoding']; 79 | if (!acceptEncoding) { 80 | acceptEncoding = ''; 81 | } 82 | 83 | // Note: this is not a conformant accept-encoding parser. 84 | // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3 85 | if (acceptEncoding.match(/\bdeflate\b/)) { 86 | response.writeHead(200, { 87 | 'content-encoding': 'deflate' 88 | }); 89 | raw.pipe(zlib.createDeflate()).pipe(response); 90 | } else if (acceptEncoding.match(/\bgzip\b/)) { 91 | response.writeHead(200, { 92 | 'content-encoding': 'gzip' 93 | }); 94 | raw.pipe(zlib.createGzip()).pipe(response); 95 | } else { 96 | response.writeHead(200, {}); 97 | raw.pipe(response); 98 | } 99 | }).listen(1337); 100 | ``` 101 | 102 | 默认情况下,Zlib 方法在截断解压缩数据时,会抛出一个错误。然而,如果已知该数据是不完整的,或仅仅是希望检查一个压缩文件的开始部分,通过改变用于压缩输入数据最后一个数据块的 flushing 方法,有可能可以抑制默认的错误处理程序: 103 | 104 | ```javascript 105 | // This is a truncated version of the buffer from the above examples 106 | const buffer = new Buffer('eJzT0yMA', 'base64'); 107 | 108 | zlib.unzip(buffer, { 109 | finishFlush: zlib.Z_SYNC_FLUSH 110 | }, (err, buffer) => { 111 | if (!err) { 112 | console.log(buffer.toString()); 113 | } else { 114 | // handle error 115 | } 116 | }); 117 | ``` 118 | 119 | 这不会改变其他情况下抛出错误的行为,例如,当输入无效格式的数据。使用该方法,这将不可能确定输入是否提前结束或是否缺乏完整性检查,因此有必要手动检查该解压缩结果的有效性。 -------------------------------------------------------------------------------- /http/class_http_Agent.md: -------------------------------------------------------------------------------- 1 | # http.Agent类 2 | 3 | * [new Agent([options])](#new-agentoptions) 4 | * [agent.sockets](#agentsockets) 5 | * [agent.requests](#agentrequests) 6 | * [agent.freeSockets](#agentfreesockets) 7 | * [agent.maxSockets](#agentmaxsockets) 8 | * [agent.maxFreeSockets](#agentmaxfreesockets) 9 | * [agent.createConnection(options[, callback])](#agentcreateconnectionoptions-callback) 10 | * [agent.getName(options)](#agentgetnameoptions) 11 | * [agent.destroy()](#agentdestroy) 12 | 13 | -------------------------------------------------- 14 | 15 | 16 | HTTP 代理用于汇总在 HTTP 客户端请求中使用的 sockets。 17 | 18 | HTTP 代理也是客户端请求使用 `Connection:keep-alive` 时的默认方式。如果没有待处理的 HTTP 请求,正在等待的一个 socket,会成为自由关闭的 socket。这也意味着,当在负载状态下,但仍不要求开发者使用 KeepAlive 手动关闭 HTTP 客户端时,Node.js 池有着 keep-alive 的好处。 19 | 20 | 如果你选择使用 HTTP 的 KeepAlive,你可以创建一个将标识设置为 `true` 的 Agent 对象(详见[构造器选项](#new_agentoptions))。那么,该 Agent 将保持没用过的 sockets 都在之后使用的池中。它们将被明确标记,以便不保持 Node.js 进程运行。然而,当它们不在被使用时,明确地使用 [destroy()](agentdestroy) KeepAlive 代理仍不失为一个好方法,以便套接字被关闭。 21 | 22 | 当 socket 发出一个 `'close'` 事件或一个特殊的 `'agentRemove'` 事件时,sockets 将从代理池中移除。这意味着,如果你打算保留一个打开了很长一段时间的 HTTP 请求并且不想让它留在池中,你可以采用链式调用: 23 | 24 | ``` javascript 25 | http.get(options, (res) => { 26 | // Do stuff 27 | }).on('socket', (socket) => { 28 | socket.emit('agentRemove'); 29 | }); 30 | ``` 31 | 32 | 或者,你可以只选择完全使用 `agent:false` 退出池: 33 | 34 | ``` javascript 35 | http.get({ 36 | hostname: 'localhost', 37 | port: 80, 38 | path: '/', 39 | agent: false // create a new agent just for this one request 40 | }, (res) => { 41 | // Do stuff with response 42 | }) 43 | ``` 44 | 45 | 46 | ## new Agent([options]) 47 | 48 | * `options` {Object} 在代理中设置的配置选项。可以有以下字段: 49 | 50 | - `keepAlive` {Boolean} 保持 sockets 在池的周围以便其他的请求可以在之后使用。默认为 `false`。 51 | 52 | - `keepAliveMsecs` {Integer} 当使用 HTTP 的 KeepAlive 时,多久发送 TCP KeepAlive 报文使得 sockets 保持活跃状态。默认为 `1000`。只在 keepAlive 设置为 `true` 应用。 53 | 54 | - `maxSockets` {Number} 每个主机允许的最大 socket 数。默认为 `Infinity`。 55 | 56 | - `maxFreeSockets` {Number} 准许在自由状态下打开的最大 socket 数。只在 keepAlive 设置为 `true` 应用。默认为 `256`。 57 | 58 | 默认的 [http.globalAgent](./http.md#httpglobalagent) 被用于 [http.request()](./http.md#httprequestoptions_callback) 将所有这些值设置为各自的默认值。 59 | 60 | 要配置其中任何一个,你必须创建你自己的 [http.Agent](#new_agentoptions) 对象。 61 | 62 | ``` javascript 63 | const http = require('http'); 64 | var keepAliveAgent = new http.Agent({ keepAlive: true }); 65 | options.agent = keepAliveAgent; 66 | http.request(options, onResponseCallback); 67 | ``` 68 | 69 | 70 | ## agent.sockets 71 | 72 | 其中包含当前在代理中使用的 socket 队列的对象。不要修改。 73 | 74 | 75 | ## agent.requests 76 | 77 | 其中含有尚未被分配到 sockets 的请求队列中的对象。不要修改。 78 | 79 | 80 | ## agent.freeSockets 81 | 82 | 当使用 HTTP 的 KeepAlive 时,其中包含正在等待被 Agent 使用的 socket 队列的对象。不要修改。 83 | 84 | 85 | ## agent.maxSockets 86 | 87 | 默认设置为无穷大。决定可以为每个来源打开多少个并发的 sockets 代理。来源是一个 `'host:port'` 或 `'host:port:localAddress'` 组合。 88 | 89 | 90 | ## agent.maxFreeSockets 91 | 92 | 默认设置为 256。对于代理支持 HTTP 的 KeepAlive,这是设置的在自由状态下打开的最大 socket 数。 93 | 94 | 95 | ## agent.createConnection(options[, callback]) 96 | 97 | 产生一个用于 HTTP 请求的 socket/stream。 98 | 99 | 默认情况下,该函数类似于 [net.createConnection()](../net/net.md#netcreateconnectionoptions_connectListener)。然而,自定义代理可以重写此方法的情况下,期望具有更大的灵活性。 100 | 101 | socket/stream 可以由以下两种方法提供:从该函数返回 socket/stream,或通过 `callback` 中的 socket/stream。 102 | 103 | `callback` 有 `(err, stream)` 参数。 104 | 105 | 106 | ## agent.getName(options) 107 | 108 | 获得一个设置请求选项的唯一名称,以确定连接是否可以再利用。在 HTTP 代理中,这会返回 `host:port:localAddress`。在 HTTPS 代理中,该名称包括CA,证书,暗号和其他 HTTPS 或特定 TLS 选项来确定 socket 的可重用性。 109 | 110 | 选项: 111 | 112 | * `host`:发出请求的服务器的域名或 IP 地址。 113 | 114 | * `port`:远程服务器的端口。 115 | 116 | * `localAddress`:在本地接口发出请求时绑定的网络连接。 117 | 118 | 119 | ## agent.destroy() 120 | 121 | 注销当前代理正在使用的任何 sockets。 122 | 123 | 通常没有必要做这一点。然而,如果你使用的是启用 KeepAlive 的代理,那么当你知道它不再被使用时,最好明确关闭代理。否则,在服务器终止之前 sockets 可能会被挂起开放相当长的时间。 -------------------------------------------------------------------------------- /crypto/class_DiffieHellman.md: -------------------------------------------------------------------------------- 1 | # DiffieHellman类 2 | 3 | * [diffieHellman.verifyError](#diffiehellmanverifyerror) 4 | * [diffieHellman.generateKeys([encoding])](#diffiehellmangeneratekeysencoding) 5 | * [diffieHellman.getGenerator([encoding])](#diffiehellmangetgeneratorencoding) 6 | * [diffieHellman.setPublicKey(public_key[, encoding])](#diffiehellmansetpublickeypublickey-encoding) 7 | * [diffieHellman.getPublicKey([encoding])](#diffiehellmangetpublickeyencoding) 8 | * [diffieHellman.setPrivateKey(private_key[, encoding])](#diffiehellmansetprivatekeyprivatekey-encoding) 9 | * [diffieHellman.getPrivateKey([encoding])](#diffiehellmangetprivatekeyencoding) 10 | * [diffieHellman.getPrime([encoding])](#diffiehellmangetprimeencoding) 11 | * [diffieHellman.computeSecret(other_public_key[, input_encoding][, output_encoding])](#diffiehellmancomputesecretotherpublickey-inputencoding-outputencoding) 12 | 13 | -------------------------------------------------- 14 | 15 | `DiffieHellman` 类是一个用于创建 Diffie-Hellman 密钥交换的工具类。 16 | 17 | `DiffieHellman` 类的实例可以使用 [crypto.createDiffieHellman()](./crypto.md#cryptocreatediffiehellmanprime-primeencoding-generator-generatorencoding) 函数来创建。 18 | 19 | ``` javascript 20 | const crypto = require('crypto'); 21 | const assert = require('assert'); 22 | 23 | // Generate Alice's keys... 24 | const alice = crypto.createDiffieHellman(2048); 25 | const alice_key = alice.generateKeys(); 26 | 27 | // Generate Bob's keys... 28 | const bob = crypto.createDiffieHellman(alice.getPrime(), alice.getGenerator()); 29 | const bob_key = bob.generateKeys(); 30 | 31 | // Exchange and generate the secret... 32 | const alice_secret = alice.computeSecret(bob_key); 33 | const bob_secret = bob.computeSecret(alice_key); 34 | 35 | // OK 36 | assert.equal(alice_secret.toString('hex'), bob_secret.toString('hex')); 37 | ``` 38 | 39 | 40 | ## diffieHellman.verifyError 41 | 42 | 一个包含检查在执行 `DiffieHellman` 对象初始化过程中所产生的任何警告和/或错误的位字段。 43 | 44 | 以下值对此属性有效(定义在 `constants` 模块中): 45 | 46 | * `DH_CHECK_P_NOT_SAFE_PRIME` 47 | 48 | * `DH_CHECK_P_NOT_PRIME` 49 | 50 | * `DH_UNABLE_TO_CHECK_GENERATOR` 51 | 52 | * `DH_NOT_SUITABLE_GENERATOR` 53 | 54 | 55 | ## diffieHellman.generateKeys([encoding]) 56 | 57 | 生成私有和公开 Diffie-Hellman 键值,并返回指定 `encoding` 的公钥。这个密钥应该转移到另一方。编码可以是 `'binary'`、`'hex'` 或 `'base64'`。如果提供了 `encoding` 则返回一个字符串,否则返回一个 [Buffer](../buffer/)。 58 | 59 | 60 | ## diffieHellman.getGenerator([encoding]) 61 | 62 | 返回指定 `encoding` 的 Diffie-Hellman 生成器。`encoding` 可以是 `'binary'`、`'hex'` 或 `'base64'`。如果提供了 `encoding` 则返回一个字符串,否则返回一个 [Buffer](../buffer/)。 63 | 64 | 65 | ## diffieHellman.setPublicKey(public_key[, encoding]) 66 | 67 | 设置一个 Diffie-Hellman 公钥。如果提供了 `encoding` 参数,且是 `'binary'`、`'hex'` 或 `'base64'` 中的一种,则 `public_key` 期望是一个字符串。如果没有提供 `encoding`,则 `public_key` 期望是一个 [Buffer](../buffer/)。 68 | 69 | 70 | ## diffieHellman.getPublicKey([encoding]) 71 | 72 | 返回指定 `encoding` 的 Diffie-Hellman 公钥。`encoding` 可以是 `'binary'`、`'hex'` 或 `'base64'`。如果提供了 `encoding` 则返回一个字符串,否则返回一个 [Buffer](../buffer/)。 73 | 74 | 75 | ## diffieHellman.setPrivateKey(private_key[, encoding]) 76 | 77 | 设置一个 Diffie-Hellman 私钥。如果提供了 `encoding` 参数,且是 `'binary'`、`'hex'` 或 `'base64'` 中的一种,则 `private_key` 期望是一个字符串。如果没有提供 `encoding`,则 `private_key` 期望是一个 [Buffer](../buffer/)。 78 | 79 | 80 | ## diffieHellman.getPrivateKey([encoding]) 81 | 82 | 返回指定 `encoding` 的 Diffie-Hellman 私钥。`encoding` 可以是 `'binary'`、`'hex'` 或 `'base64'`。如果提供了 `encoding` 则返回一个字符串,否则返回一个 [Buffer](../buffer/)。 83 | 84 | 85 | ## diffieHellman.getPrime([encoding]) 86 | 87 | 返回指定 `encoding` 的 Diffie-Hellman 素数。`encoding` 可以是 `'binary'`、`'hex'` 或 `'base64'`。如果提供了 `encoding` 则返回一个字符串,否则返回一个 [Buffer](../buffer/)。 88 | 89 | 90 | ## diffieHellman.computeSecret(other_public_key[, input_encoding][, output_encoding]) 91 | 92 | 使用 `other_public_key` 作为对方的公钥计算共享密钥并返回计算后的共享密钥。使用指定的 `input_encoding` 解释提供的密钥,并返回使用指定 `output_encoding` 编码的密钥。编码可以是 `'binary'`、`'hex'` 或 `'base64'`。如果没有提供 `input_encoding`,`other_public_key` 期望是一个 [Buffer](../buffer/)。 93 | 94 | 如果给出了 `output_encoding`,将返回一个字符串;否则,返回一个 [Buffer](../buffer/)。 -------------------------------------------------------------------------------- /crypto/class_Cipher.md: -------------------------------------------------------------------------------- 1 | # Cipher类 2 | 3 | * [cipher.setAAD(buffer)](#ciphersetaadbuffer) 4 | * [cipher.setAutoPadding(auto_padding=true)](#ciphersetautopaddingautopaddingtrue) 5 | * [cipher.getAuthTag()](#ciphergetauthtag) 6 | * [cipher.update(data[, input_encoding][, output_encoding])](#cipherupdatedata-inputencoding-outputencoding) 7 | * [cipher.final([output_encoding])](#cipherfinaloutputencoding) 8 | 9 | -------------------------------------------------- 10 | 11 | `Cipher` 类的实例用于加密数据。该类可以以两种方式进行使用: 12 | 13 | * 作为可读和可写的[流](../stream/),写入简单的未加密数据并在可读端上产生加密数据; 14 | 15 | * 使用 [cipher.update()](#cipherupdatedata-inputencoding-outputencoding) 和 [cipher.final()](#cipherfinaloutputencoding) 方法来产生加密数据。 16 | 17 | [crypto.createCipher()](./crypto.md#cryptocreatecipheralgorithm-password) 和 [crypto.createCipheriv()](./crypto.md#cryptocreatecipherivalgorithm-key-iv) 方法用于创建 `Cipher` 实例。`Cipher` 对象无法直接使用 `new` 关键词创建。 18 | 19 | 示例:将 `Cipher` 对象用作流: 20 | 21 | ``` javascript 22 | const crypto = require('crypto'); 23 | const cipher = crypto.createCipher('aes192', 'a password'); 24 | 25 | var encrypted = ''; 26 | cipher.on('readable', () => { 27 | var data = cipher.read(); 28 | if (data) 29 | encrypted += data.toString('hex'); 30 | }); 31 | cipher.on('end', () => { 32 | console.log(encrypted); 33 | // Prints: ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504 34 | }); 35 | 36 | cipher.write('some clear text data'); 37 | cipher.end(); 38 | ``` 39 | 40 | 示例:使用 `Cipher` 并导流: 41 | 42 | ``` javascript 43 | const crypto = require('crypto'); 44 | const fs = require('fs'); 45 | const cipher = crypto.createCipher('aes192', 'a password'); 46 | 47 | const input = fs.createReadStream('test.js'); 48 | const output = fs.createWriteStream('test.enc'); 49 | 50 | input.pipe(cipher).pipe(output); 51 | ``` 52 | 53 | 示例:使用 [cipher.update()](#cipherupdatedata-inputencoding-outputencoding) 和 [cipher.final()](#cipherfinaloutputencoding) 方法: 54 | 55 | ``` javascript 56 | const crypto = require('crypto'); 57 | const cipher = crypto.createCipher('aes192', 'a password'); 58 | 59 | var encrypted = cipher.update('some clear text data', 'utf8', 'hex'); 60 | encrypted += cipher.final('hex'); 61 | console.log(encrypted); 62 | // Prints: ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504 63 | ``` 64 | 65 | 66 | ## cipher.setAAD(buffer) 67 | 68 | 使用验证加密模式(目前仅支持 `GCM`)时,`cipher.setAAD()` 方法设置的值用于*附加认证数据*(AAD)输入参数。 69 | 70 | 71 | ## cipher.setAutoPadding(auto_padding=true) 72 | 73 | 当使用块加密算法时,`Cipher` 类会自动添加适当块大小的填充到输入数据中。调用 `cipher.setAutoPadding(false)` 禁用默认填充。 74 | 75 | 当 `auto_padding` 为 `false` 时,整个输入数据的长度必须是加密块大小的倍数,否则,[cipher.final()](#cipherfinaloutputencoding) 会抛出一个错误。禁用自动填充对于非标准填充有用,例如使用 `0x0` 而不是 PKCS 填充。 76 | 77 | `cipher.setAutoPadding()` 方法必须在 [cipher.final()](#cipherfinaloutputencoding) 之前调用。 78 | 79 | 80 | ## cipher.getAuthTag() 81 | 82 | 使用验证加密模式(目前仅支持 `GCM`)时,`cipher.getAuthTag()` 方法返回一个包含已经从给定数据计算得出的*认证标签*的 [Buffer](../buffer/)。 83 | 84 | `cipher.getAuthTag()` 方法只应在使用 [cipher.final()](#cipherfinaloutputencoding) 方法完成加密后才能调用。 85 | 86 | 87 | ## cipher.update(data[, input_encoding][, output_encoding]) 88 | 89 | 用 `data` 更新加密内容。如果给定了 `input_encoding` 参数,它的值必须是 `'utf8'`、`'ascii'` 或 `'binary'` 其中之一并且 `data` 参数是使用指定编码的字符串。如果没有给定 `input_encoding` 参数,`data` 必须是一个 [Buffer](../buffer/)。如果 `data` 是一个 [Buffer](../buffer/),那么 `input_encoding` 参数会被忽略。 90 | 91 | `output_encoding` 指定加密数据的输出格式,可以是 `'binary'`、`'base64'` 或 `'hex'`。如果指定了 `output_encoding`,将返回使用指定编码的字符串。如果没有提供 `output_encoding`,将返回一个 [Buffer](../buffer/)。 92 | 93 | `cipher.update()` 方法可以在新数据上多次调用,直到调用 [cipher.final()](#cipherfinaloutputencoding)。在 [cipher.final()](#cipherfinaloutputencoding) 之后调用 `cipher.update()` 将导致抛出错误。 94 | 95 | 96 | ## cipher.final([output_encoding]) 97 | 98 | 返回任何剩余的加密内容。如果 `output_encoding` 参数是 `'binary'`、`'base64'` 或 `'hex'` 中的一个,将返回一个字符串。如果没有提供 `output_encoding`,将返回一个 [Buffer](../buffer/)。 99 | 100 | 一旦调用了 `cipher.final()` 方法,`Cipher` 对象不能再用于加密数据。尝试多次调用 `cipher.final()` 将导致抛出错误。 -------------------------------------------------------------------------------- /crypto/class_Decipher.md: -------------------------------------------------------------------------------- 1 | # Decipher类 2 | 3 | * [decipher.setAAD(buffer)](#deciphersetaadbuffer) 4 | * [decipher.setAutoPadding(auto_padding=true)](#deciphersetautopaddingautopaddingtrue) 5 | * [decipher.setAuthTag(buffer)](#deciphersetauthtagbuffer) 6 | * [decipher.update(data[, input_encoding][, output_encoding])](#decipherupdatedata-inputencoding-outputencoding) 7 | * [decipher.final([output_encoding])](#decipherfinaloutputencoding) 8 | 9 | -------------------------------------------------- 10 | 11 | `Decipher` 类的实例用于解密数据。该类可以以两种方式进行使用: 12 | 13 | * 作为可读和可写的[流](../stream/),写入简单的加密数据并在可读端上产生未加密数据; 14 | 15 | * 使用 [decipher.update()](#decipherupdatedata-inputencoding-outputencoding) 和 [decipher.final()](#decipherfinaloutputencoding) 方法来产生加密数据。 16 | 17 | [crypto.createDecipher()](./crypto.md#cryptocreatedecipheralgorithm-password) 和 [crypto.createDecipheriv()](./crypto.md#cryptocreatedecipherivalgorithm-key-iv) 方法用于创建 `Decipher` 实例。`Decipher` 对象无法直接使用 `new` 关键词创建。 18 | 19 | 示例:将 `Decipher` 对象用作流: 20 | 21 | ``` javascript 22 | const crypto = require('crypto'); 23 | const decipher = crypto.createDecipher('aes192', 'a password'); 24 | 25 | var decrypted = ''; 26 | decipher.on('readable', () => { 27 | var data = decipher.read(); 28 | if (data) 29 | decrypted += data.toString('utf8'); 30 | }); 31 | decipher.on('end', () => { 32 | console.log(decrypted); 33 | // Prints: some clear text data 34 | }); 35 | 36 | var encrypted = 'ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504'; 37 | decipher.write(encrypted, 'hex'); 38 | decipher.end(); 39 | ``` 40 | 41 | 示例:使用 `Decipher` 并导流: 42 | 43 | ``` javascript 44 | const crypto = require('crypto'); 45 | const fs = require('fs'); 46 | const decipher = crypto.createDecipher('aes192', 'a password'); 47 | 48 | const input = fs.createReadStream('test.enc'); 49 | const output = fs.createWriteStream('test.js'); 50 | 51 | input.pipe(decipher).pipe(output); 52 | ``` 53 | 54 | 示例:使用 [decipher.update()](#decipherupdatedata-inputencoding-outputencoding) 和 [decipher.final()](#decipherfinaloutputencoding) 方法: 55 | 56 | ``` javascript 57 | const crypto = require('crypto'); 58 | const decipher = crypto.createDecipher('aes192', 'a password'); 59 | 60 | var encrypted = 'ca981be48e90867604588e75d04feabb63cc007a8f8ad89b10616ed84d815504'; 61 | var decrypted = decipher.update(encrypted, 'hex', 'utf8'); 62 | decrypted += decipher.final('utf8'); 63 | console.log(decrypted); 64 | // Prints: some clear text data 65 | ``` 66 | 67 | 68 | ## decipher.setAAD(buffer) 69 | 70 | 使用验证加密模式(目前仅支持 `GCM`)时,`decipher.setAAD()` 方法设置的值用于*附加认证数据*(AAD)输入参数。 71 | 72 | 73 | ## decipher.setAutoPadding(auto_padding=true) 74 | 75 | 当数据已经被加密而没有标准块填充时,调用 `decipher.setAutoPadding(false)` 将禁用自动填充防止 [decipher.final()](#decipherfinaloutputencoding) 检查和删除填充。 76 | 77 | 关闭自动填充功能仅在输入数据的长度是加密块大小的倍数时有效。 78 | 79 | `decipher.setAutoPadding()` 方法必须在 [decipher.update()](#decipherupdatedata-inputencoding-outputencoding) 之前调用。 80 | 81 | 82 | ## decipher.setAuthTag(buffer) 83 | 84 | 使用验证加密模式(目前仅支持 `GCM`)时,`decipher.setAuthTag()` 方法用于传入接收的*认证标签*。如果没有提供标签,或者如果密文已经被篡改,[decipher.final()](#decipherfinaloutputencoding) 会抛出由于认证失败而应丢弃密文的指示。 85 | 86 | 87 | ## cipher.update(data[, input_encoding][, output_encoding]) 88 | 89 | 用 `data` 更新解密内容。如果给定了 `input_encoding` 参数,它的值必须是 `'utf8'`、`'ascii'` 或 `'binary'` 其中之一并且 `data` 参数是使用指定编码的字符串。如果没有给定 `input_encoding` 参数,`data` 必须是一个 [Buffer](../buffer/)。如果 `data` 是一个 [Buffer](../buffer/),那么 `input_encoding` 参数会被忽略。 90 | 91 | `output_encoding` 指定加密数据的输出格式,可以是 `'binary'`、`'base64'` 或 `'hex'`。如果指定了 `output_encoding`,将返回使用指定编码的字符串。如果没有提供 `output_encoding`,将返回一个 [Buffer](../buffer/)。 92 | 93 | `decipher.update()` 方法可以在新数据上多次调用,直到调用 [decipher.final()](#decipherfinaloutputencoding)。在 [decipher.final()](#decipherfinaloutputencoding) 之后调用 `decipher.update()` 将导致抛出错误。 94 | 95 | 96 | ## cipher.final([output_encoding]) 97 | 98 | 返回任何剩余的解密内容。如果 `output_encoding` 参数是 `'binary'`、`'base64'` 或 `'hex'` 中的一个,将返回一个字符串。如果没有提供 `output_encoding`,将返回一个 [Buffer](../buffer/)。 99 | 100 | 一旦调用了 `decipher.final()` 方法,`Decipher` 对象不能再用于解密数据。尝试多次调用 `decipher.final()` 将导致抛出错误。 -------------------------------------------------------------------------------- /addons/hello_world.md: -------------------------------------------------------------------------------- 1 | # Hello world 2 | 3 | * [构建](#building) 4 | * [链接到 Node.js 自己的依赖](linking_to_nodejs_own_dependencies) 5 | * [使用 require() 加载插件](loading_addons) 6 | 7 | -------------------------------------------------- 8 | 9 | 10 | 这个“Hello World”示例是一个简单的插件,用 C++ 编写,这等同于如下的 JavaScript代码: 11 | 12 | ```javascript 13 | module.exports.hello = () => 'world'; 14 | ``` 15 | 16 | 首先创建 `hello.cc` 文件: 17 | 18 | ```c++ 19 | // hello.cc 20 | #include 21 | 22 | namespace demo { 23 | 24 | using v8::FunctionCallbackInfo; 25 | using v8::Isolate; 26 | using v8::Local; 27 | using v8::Object; 28 | using v8::String; 29 | using v8::Value; 30 | 31 | void Method(const FunctionCallbackInfo& args) { 32 | Isolate* isolate = args.GetIsolate(); 33 | args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world")); 34 | } 35 | 36 | void init(Local exports) { 37 | NODE_SET_METHOD(exports, "hello", Method); 38 | } 39 | 40 | NODE_MODULE(addon, init) 41 | 42 | } // namespace demo 43 | ``` 44 | 45 | 请注意,所有的 Node.js 插件必须导出如下格式的初始化函数: 46 | 47 | 48 | ```c++ 49 | void Initialize(Local exports); 50 | NODE_MODULE(module_name, Initialize) 51 | ``` 52 | 53 | 这里在 `NODE_MODULE` 后面没有分号,以表示它不是函数(详见 `node.h`)。 54 | 55 | `module_name` 必须匹配最终二进制的文件名(不包括 .node 后缀)。 56 | 57 | 在 `hello.cc` 例子中,那么,`init` 是初始化函数,并且 `addon` 是插件模块的名称。 58 | 59 | 60 |
61 | ### 构建 62 | 63 | 一旦源代码已被写入,它必须被编译成二进制 `addon.node` 文件。要做到这一点,在项目的顶层使用类 JSON 的格式描述你的模块构建配置,用于创建一个叫做 `binding.gyp` 的文件。该文件通过 [node-gyp](https://github.com/nodejs/node-gyp) 使用 —— 专门写了一个用于编译 Node.js 插件的工具。 64 | 65 | ``` 66 | { 67 | "targets": [ 68 | { 69 | "target_name": "addon", 70 | "sources": ["hello.cc"] 71 | } 72 | ] 73 | } 74 | ``` 75 | 76 | *注意:一个实用的 `node-gyp` 版本作为 `npm` 的一部分,通过 Node.js 捆绑和发行。此版本没有做出可以直接供开发者使用的版本,目的只是为了支持使用 `npm install` 命令编译并安装插件的能力。希望直接使用 `node-gyp` 的开发者可以使用 `npm install -g node-gyp` 命令进行安装。查阅 `node-gyp` [安装说明](https://github.com/nodejs/node-gyp#installation)了解更多详情,包括平台特定的要求。* 77 | 78 | 一旦 `binding.gyp` 文件被创建,使用 `node-gyp configure` 为当前平台生成相应项目的构建文件。这会在 `build/` 目录下生成一个 `Makefile` (在 Unix 平台上)或 `vcxproj` 文件(在 Windows 上)。 79 | 80 | 下一步,调用 `node-gyp build` 命令生成 `addon.node` 的编译文件。这会被放到 `build/Release/` 目录下。 81 | 82 | 当使用 `npm install` 安装一个 Node.js 插件时,npm 使用自身捆绑的 `node-gyp` 版本来执行同样的一套动作,为用户的需要的平台产生一个插件的编译版本。 83 | 84 | 一旦构建完成,二进制插件就可以通过 `require()` 指向内置的 `addon.node` 模块在 Node.js 内部使用: 85 | 86 | ```javascript 87 | // hello.js 88 | const addon = require('./build/Release/addon'); 89 | 90 | console.log(addon.hello()); // 'world' 91 | ``` 92 | 93 | 请参阅下面例子获取详细信息或在 [https://github.com/arturadib/node-qt](https://github.com/arturadib/node-qt) 了解关于生产环境中的例子。 94 | 95 | 因为编译后的二进制插件的确切路径可能取决于它是如何编译的(如,有时它可能在 `./build/Debug/`),插件可以使用[绑定](https://github.com/TooTallNate/node-bindings)包加载已编译的模块。 96 | 97 | 请注意,虽然 `bindings` 包在如何定位插件模块的实现上更精细,但它本质上是使用类似于一个 `try-catch` 的模式: 98 | 99 | ```javascript 100 | try { 101 | return require('./build/Release/addon.node'); 102 | } catch (err) { 103 | return require('./build/Debug/addon.node'); 104 | } 105 | ``` 106 | 107 | 108 |
109 | ### 链接到 Node.js 自己的依赖 110 | 111 | Node.js 使用了一些静态链接库,比如 V8 引擎、libuv 和 OpenSSL。所有的插件都需要链接到 V8,并且也可能链接到任何其他的依赖。通常情况下,只要简单的包含相应的 `#include <...>` 声明(如,`#include `),并且 `node-gyp` 会找到适当的头。不过,也有一些注意事项需要注意: 112 | 113 | * 当 `node-gyp` 运行时,它会检测 Node.js 的具体发行版本,并下载完整源码包,或只是头。如果下载了全部的源码,插件将会有完整的权限去访问 Node.js 的全套依赖。然而,如果只下载了 Node.js 的头,则仅由 Node.js 导出的标记可用。 114 | 115 | * `node-gyp` 可以使用指向本地 Node.js 源代码信息的 `--nodedir` 标识来运行。使用此选项,插件将有机会访问全套依赖。 116 | 117 | 118 |
119 | ### 使用 require() 加载插件 120 | 121 | 编译后的二进制插件的文件扩展名是 `.node`(而不是 `.dll` 或 `.so`)。[require()](../globals/global.md#require) 函数是被用于查找具有 `.node` 文件扩展名的文件,并初始化这些作为动态链接库。 122 | 123 | 当调用 [require()](../globals/global.md#require) 时,`.node` 拓展名通常是可以省略的,Node.js 仍可以发现并初始化该插件。警告,然而,Node.js 会首先尝试查找并加载模块或碰巧共享相同的基本名称的 JavaScript 文件。例如,如果有一个 `addon.js` 文件与二进制 `addon.node`在同一目录下,那么 [require('addon')](../globals/global.md#require) 将优先考虑 `addon.js` 文件并加载它来代替 `addon.node`。 -------------------------------------------------------------------------------- /errors/error_propagation_and_interception.md: -------------------------------------------------------------------------------- 1 | # 错误的冒泡和捕捉 2 | 3 | * [Node.js 风格的回调](#nodejs-风格的回调) 4 | 5 | -------------------------------------------------- 6 | 7 | 8 | Node.js 支持几种在程序运行时发生的错误冒泡和错误处理机制。如何报告和处理这些错误完全取决于 `Error` 的类型和被调用的 API 的风格。 9 | 10 | 所有的 JavaScript 错误都是作为异常处理的,*立即*产生并通过标准的 JavaScript `throw` 机制抛出错误。这些都是利用 JavaScript 语言提供的 [try / catch construct](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/try...catch) 处理的。 11 | 12 | ```javascript 13 | // Throws with a ReferenceError because z is undefined 14 | try { 15 | const m = 1; 16 | const n = m + z; 17 | } catch (err) { 18 | // Handle the error here. 19 | } 20 | ``` 21 | 22 | JavaScript 的 `throw` 机制在任何时候使用都会引发异常,*必须*通过 `try / catch` 处理,否则 Node.js 会立即退出进程。 23 | 24 | 但也有少数例外,*同步*的 API(任何不接受 `callback` 函数的阻塞方法,例如,[fs.readFileSync](../fs/fs.md#readFileSync))会使用 `throw` 报告错误。 25 | 26 | 异步的 API 中发生的错误可能会以多种方式进行报告: 27 | 28 | * 大多数的异步方法都接受一个 `callback` 函数,该函数接受给其第一个参数传递一个 `Error` 对象。如果第一个参数不是 `null` 或是一个 `Error` 实例,就应该对发生的错误进行处理。 29 | 30 | ```javascript 31 | const fs = require('fs'); 32 | fs.readFile('a file that does not exist', (err, data) => { 33 | if (err) { 34 | console.error('There was an error reading the file!', err); 35 | return; 36 | } 37 | // Otherwise handle the data 38 | }); 39 | ``` 40 | 41 | * 当 `EventEmitter` 对象调用一个异步方法时,错误会被分发到该对象的 `'error'` 事件上。 42 | 43 | ```javascript 44 | const net = require('net'); 45 | const connection = net.connect('localhost'); 46 | 47 | // Adding an 'error' event handler to a stream: 48 | connection.on('error', (err) => { 49 | // If the connection is reset by the server, or if it can't 50 | // connect at all, or on any sort of error encountered by 51 | // the connection, the error will be sent here. 52 | console.error(err); 53 | }); 54 | 55 | connection.pipe(process.stdout); 56 | ``` 57 | 58 | * 在 Node.js API 中有一小部分普通的异步方法仍可能使用 `throw` 机制引发错误,必须使用 `try / catch` 处理。这些方法并没有一个完整的列表。请参阅各类方法的文档以确定所需的合适的错误处理机制。 59 | 60 | 大多数的 [stream-based](../stream/) 和 [event emitter-based](../events/class_EventEmitter.md#) API 都使用相同的 `'error'` 事件机制,它们本身就代表了一系列随着时间推移的异步操作(相对于单一操作,可能有效也可能无效)。 61 | 62 | 对于*所有*的 `EventEmitter` 对象而言,如果不能提供一个 `'error'` 事件处理程序,那么错误将被抛出,从而导致 Node.js 进程报告一个未处理的异常并随即崩溃,除非适当的使用 [域](../domain/) 模块或已经注册了 [process.on('uncaughtException')](../process/process.md#uncaughtException) 事件。 63 | 64 | ```javascript 65 | const EventEmitter = require('events'); 66 | const ee = new EventEmitter(); 67 | 68 | setImmediate(() => { 69 | // This will crash the process because no 'error' event 70 | // handler has been added. 71 | ee.emit('error', new Error('This will crash')); 72 | }); 73 | ``` 74 | 75 | 在调用的代码退出后抛出的错误,不能通过 `try / catch` 截获。 76 | 77 | 开发者必须查阅各类方法的文档以明确在错误发生时这些方法是如何冒泡的。 78 | 79 | 80 |
81 | ## Node.js 风格的回调 82 | 83 | 大多数由 Node.js 核心 API 暴露出来的异步方法都遵循称之为“Node.js 风格的回调”的惯用模式。通过这种模式,可以用作为参数的方法传递函数。当操作完成或引发错误时,`Error` 对象(无论如何)都会作为第一个参数被回调函数所调用。如果没有引发错误,第一个参数会作为 `null` 传递。 84 | 85 | ```javascript 86 | const fs = require('fs'); 87 | 88 | function nodeStyleCallback(err, data) { 89 | if (err) { 90 | console.error('There was an error', err); 91 | return; 92 | } 93 | console.log(data); 94 | } 95 | 96 | fs.readFile('/some/file/that/does-not-exist', nodeStyleCallback); 97 | fs.readFile('/some/file/that/does-exist', nodeStyleCallback) 98 | ``` 99 | 100 | JavaScript 的 `try / catch` 机制**不应该**用于截取由异步 API 引起的错误。尝试使用 `throw` 替代一个 Node.js 风格的回调是一个初学者常犯的错误: 101 | 102 | ```javascript 103 | // THIS WILL NOT WORK: 104 | const fs = require('fs'); 105 | 106 | try { 107 | fs.readFile('/some/file/that/does-not-exist', (err, data) => { 108 | // mistaken assumption: throwing here... 109 | if (err) { 110 | throw err; 111 | } 112 | }); 113 | } catch (err) { 114 | // This will not catch the throw! 115 | console.log(err); 116 | } 117 | ``` 118 | 119 | 这并没有什么用,因为 `fs.readFile()` 是一个异步调用的回调函数。当回调函数被调用时,这些代码(包括 `try { } catch(err) { }` 区域)就已经退出。在大对数案例中,抛出回调函数中的错误会**引起 Node.js 进程崩溃**。如果[域](../domain/)被启用,或已注册了 [process.on('uncaughtException')](../process/process.md#uncaughtException) 事件,那么这样的错误是可以被拦截的。 -------------------------------------------------------------------------------- /zlib/zlib.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [zlib.createGzip([options])](#createGzip) 4 | * [zlib.createGunzip([options])](#createGunzip) 5 | * [zlib.createUnzip([options])](#createUnzip) 6 | * [zlib.createDeflate([options])](#createDeflate) 7 | * [zlib.createInflate([options])](#createInflate) 8 | * [zlib.createDeflateRaw([options])](#createDeflateRaw) 9 | * [zlib.createInflateRaw([options])](#createInflateRaw) 10 | 11 | ### 便捷方法 12 | 13 | * [zlib.gzip(buf[, options], callback)](#gzip) 14 | * [zlib.gzipSync(buf[, options])](#gzipSync) 15 | * [zlib.gunzip(buf[, options], callback)](#gunzip) 16 | * [zlib.gunzipSync(buf[, options])](#gunzipSync) 17 | * [zlib.unzip(buf[, options], callback)](#unzip) 18 | * [zlib.unzipSync(buf[, options])](#unzipSync) 19 | * [zlib.deflate(buf[, options], callback)](#deflate) 20 | * [zlib.deflateSync(buf[, options])](#deflateSync) 21 | * [zlib.inflate(buf[, options], callback)](#inflate) 22 | * [zlib.inflateSync(buf[, options])](#inflateSync) 23 | * [zlib.deflateRaw(buf[, options], callback)](#deflateRaw) 24 | * [zlib.deflateRawSync(buf[, options])](#deflateRawSync) 25 | * [zlib.inflateRaw(buf[, options], callback)](#inflateRaw) 26 | * [zlib.inflateRawSync(buf[, options])](#inflateRawSync) 27 | 28 | -------------------------------------------------- 29 | 30 | 31 |
32 | ## zlib.createGzip([options]) 33 | 34 | 返回一个用 [options](./class_options.md#) 生成的新的 [Gzip](./zlib_class.md#Gzip) 对象。 35 | 36 | 37 |
38 | ## zlib.createGunzip([options]) 39 | 40 | 返回一个用 [options](./class_options.md#) 生成的新的 [Gunzip](./zlib_class.md#Gunzip) 对象。 41 | 42 | 43 |
44 | ## zlib.createUnzip([options]) 45 | 46 | 返回一个用 [options](./class_options.md#) 生成的新的 [Unzip](./zlib_class.md#Unzip) 对象。 47 | 48 | 49 |
50 | ## zlib.createDeflate([options]) 51 | 52 | 返回一个用 [options](./class_options.md#) 生成的新的 [Deflate](./zlib_class.md#Deflate) 对象。 53 | 54 | 55 |
56 | ## zlib.createInflate([options]) 57 | 58 | 返回一个用 [options](./class_options.md#) 生成的新的 [Inflate](./zlib_class.md#Inflate) 对象。 59 | 60 | 61 |
62 | ## zlib.createDeflateRaw([options]) 63 | 64 | 返回一个用 [options](./class_options.md#) 生成的新的 [DeflateRaw](./zlib_class.md#DeflateRaw) 对象。 65 | 66 | 67 |
68 | ## zlib.createInflateRaw([options]) 69 | 70 | 返回一个用 [options](./class_options.md#) 生成的新的 [InflateRaw](./zlib_class.md#InflateRaw) 对象。 71 | 72 | 73 |
74 | ### zlib.gzip(buf[, options], callback) 75 |
76 | ### zlib.gzipSync(buf[, options]) 77 | 78 | 通过 Gzip 来压缩一个 Buffer 或字符串。 79 | 80 | 81 |
82 | ### zlib.gunzip(buf[, options], callback) 83 |
84 | ### zlib.gunzipSync(buf[, options]) 85 | 86 | 通过 Gunzip 来解压缩一个 Buffer 或字符串。 87 | 88 | 89 |
90 | ### zlib.unzip(buf[, options], callback) 91 |
92 | ### zlib.unzipSync(buf[, options]) 93 | 94 | 通过 Unzip 来解压缩一个 Buffer 或字符串。 95 | 96 | 97 |
98 | ### zlib.deflate(buf[, options], callback) 99 |
100 | ### zlib.deflateSync(buf[, options]) 101 | 102 | 通过 Deflate 来压缩一个 Buffer 或字符串。 103 | 104 | 105 |
106 | ### zlib.inflate(buf[, options], callback) 107 |
108 | ### zlib.inflateSync(buf[, options]) 109 | 110 | 通过 Inflate 来解压缩一个 Buffer 或字符串。 111 | 112 | 113 |
114 | ### zlib.deflateRaw(buf[, options], callback) 115 |
116 | ### zlib.deflateRawSync(buf[, options]) 117 | 118 | 通过 DeflateRaw 来压缩一个 Buffer 或字符串。 119 | 120 | 121 |
122 | ### zlib.inflateRaw(buf[, options], callback) 123 |
124 | ### zlib.inflateRawSync(buf[, options]) 125 | 126 | 通过 InflateRaw 来解压缩一个 Buffer 或字符串。 -------------------------------------------------------------------------------- /vm/class_Script.md: -------------------------------------------------------------------------------- 1 | # Script类 2 | 3 | * [new vm.Script(code, options)](#new_vm_Script) 4 | * [script.runInThisContext([options])](#runInThisContext) 5 | * [script.runInContext(contextifiedSandbox[, options])](#runInContext) 6 | * [script.runInNewContext([sandbox][, options])](#runInNewContext) 7 | 8 | -------------------------------------------------- 9 | 10 | 11 | 一个保存预编译脚本的类,并在特定的沙箱中运行它们。 12 | 13 |
14 | ## new vm.Script(code, options) 15 | 16 | 创建一个新的 `Script` 编译 `code`,但不运行它。相反,被创建的 `vm.Script` 对象用于表示此编译代码。此脚本可以在之后使用以下方法运行多次。返回的脚本不绑定到任何全局对象。它在每次运行前定向绑定。 17 | 18 | 创建脚本时的选项有: 19 | 20 | * `filename`:允许你控制从该脚本中产生的任何堆栈跟踪中显示的文件名 21 | 22 | * `lineOffset`:允许你添加一个显示在堆栈跟踪中行号的偏移量。 23 | 24 | * `columnOffset`:允许你添加一个显示在堆栈跟踪中列数的偏移量。 25 | 26 | * `displayErrors`:是否在抛出异常前输出带高亮错误代码行的错误信息到 stderr。仅适用于编译代码时的语法错误;而运行代码时的错误,通过脚本的方法选项来控制。 27 | 28 | * `timeout`:在终止执行之前,执行 `code` 的毫秒数。如果执行被终止,[错误](../errors/class_Error.md#)将被抛出。 29 | 30 | * `cachedData`:一个可选的 `Buffer` 和提供的源代码的 V8 代码缓存数据。当提供 `cachedDataRejected` 值时会根据由 V8 接受的数据设置 `true` 或 `false`。 31 | 32 | * `produceCachedData`:如果为 `true` 并且不存在 `cachedData` - V8 试图生成代码缓存数据的 `code`。一旦成功,将产生和存储一个 `Buffer` 和 V8 的代码缓存数据到返回的 `vm.Script` 实例的缓存数据属性中。`cachedDataProduced` 值会被设置为 `true` 或 `false` 取决于代码缓存数据是否被成功产生。 33 | 34 | 35 |
36 | ## script.runInThisContext([options]) 37 | 38 | 类似于 [vm.runInThisContext()](./vm.md#runInThisContext) 但是一个预编译 `Script` 对象的方法。`script.runInThisContext()` 运行 `script` 的编译代码并返回结果。运行的代码无权限访问本地作用域,但是有权限访问当前的 `global` 对象。 39 | 40 | 使用 `script.runInThisContext()` 编译代码一次,运行多次: 41 | 42 | ``` javascript 43 | const vm = require('vm'); 44 | 45 | global.globalVar = 0; 46 | 47 | const script = new vm.Script('globalVar += 1', { filename: 'myfile.vm' }); 48 | 49 | for (var i = 0; i < 1000; ++i) { 50 | script.runInThisContext(); 51 | } 52 | 53 | console.log(globalVar); 54 | 55 | // 1000 56 | ``` 57 | 58 | 运行脚本的选项有: 59 | 60 | * `filename`:允许你控制产生在任何堆栈跟踪中显示的文件名。 61 | 62 | * `lineOffset`:允许你添加一个显示在堆栈跟踪中行号的偏移量。 63 | 64 | * `columnOffset`:允许你添加一个显示在堆栈跟踪中列数的偏移量。 65 | 66 | * `displayErrors`:是否在抛出异常前输出带高亮错误代码行的错误信息到 stderr。将捕捉从编译 `code` 时获得的语法错误和通过执行编译代码抛出的运行时错误。仅适用于执行代码的运行时错误;它不可能创建一个语法错误的 `Script` 实例作为构造函数抛出。 67 | 68 | * `timeout`:在终止执行之前,执行 `code` 的毫秒数。如果执行被终止,[错误](../errors/class_Error.md#)将被抛出。 69 | 70 | 71 |
72 | ## script.runInContext(contextifiedSandbox[, options]) 73 | 74 | 类似于 [vm.runInContext()](./vm.md#runInContext) 但是一个预编译 `Script` 对象的方法。`script.runInThisContext()` 在 `contextifiedSandbox` 中运行 `script` 的编译代码并返回结果。运行的代码无权限访问本地作用域。 75 | 76 | `script.runInContext()` 与 [script.runInThisContext()](#runInThisContext) 使用相同的选项。 77 | 78 | 例子:编译递增一个全局变量,并设置一个变量,然后执行该代码多次。这些全局变量包含在沙箱中。 79 | 80 | ``` javascript 81 | const util = require('util'); 82 | const vm = require('vm'); 83 | 84 | var sandbox = { 85 | animal: 'cat', 86 | count: 2 87 | }; 88 | 89 | var context = new vm.createContext(sandbox); 90 | var script = new vm.Script('count += 1; name = "kitty"'); 91 | 92 | for (var i = 0; i < 10; ++i) { 93 | script.runInContext(context); 94 | } 95 | 96 | console.log(util.inspect(sandbox)); 97 | 98 | // { animal: 'cat', count: 12, name: 'kitty' } 99 | ``` 100 | 101 | 请注意,运行不受信任的代码是一个棘手的事情,需要非常小心。`script.runInContext()` 非常有用,但安全运行不受信任的代码需要一个单独的进程。 102 | 103 | 104 |
105 | ## script.runInNewContext([sandbox][, options]) 106 | 107 | 类似于 [vm.runInNewContext()](./vm.md#runInNewContext) 但是一个预编译 `Script` 对象的方法。如果传入 `sandbox`,则使用 `script.runInNewContext()` 将其上下文化,然后运行 `script` 的编译代码将沙箱作为全局对象并返回结果。运行的代码无权限访问本地作用域。 108 | 109 | `script.runInNewContext()` 与 [script.runInThisContext()](#runInThisContext) 使用相同的选项。 110 | 111 | 例子:编译代码,设置一个全局变量,然后在不同的上下文中多次执行代码。这些全局变量在沙箱内部被设置。 112 | 113 | ``` javascript 114 | const util = require('util'); 115 | const vm = require('vm'); 116 | 117 | const sandboxes = [{}, {}, {}]; 118 | 119 | const script = new vm.Script('globalVar = "set"'); 120 | 121 | sandboxes.forEach((sandbox) => { 122 | script.runInNewContext(sandbox); 123 | }); 124 | 125 | console.log(util.inspect(sandboxes)); 126 | 127 | // [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }] 128 | ``` 129 | 130 | 请注意,运行不受信任的代码是一个棘手的事情,需要非常小心。`script.runInNewContext()` 非常有用,但安全运行不受信任的代码需要一个单独的进程。 -------------------------------------------------------------------------------- /crypto/class_ECDH.md: -------------------------------------------------------------------------------- 1 | # ECDH类 2 | 3 | * [ecdh.generateKeys([encoding[, format]])](#ecdhgeneratekeysencoding-format) 4 | * [ecdh.setPrivateKey(private_key[, encoding])](#ecdhsetprivatekeyprivatekey-encoding) 5 | * [ecdh.getPrivateKey([encoding])](#ecdhgetprivatekeyencoding) 6 | * [ecdh.setPublicKey(public_key[, encoding])](#ecdhsetpublickeypublickey-encoding) 7 | * [ecdh.getPublicKey([encoding[, format]])](#ecdhgetpublickeyencoding-format) 8 | * [ecdh.computeSecret(other_public_key[, input_encoding][, output_encoding])](#ecdhcomputesecretotherpublickey-inputencoding-outputencoding) 9 | 10 | -------------------------------------------------- 11 | 12 | `ECDH` 类是用来创建 Elliptic Curve Diffie-Hellman(ECDH)密钥交换的工具类。 13 | 14 | `ECDH` 类的实例可以使用 [crypto.createECDH()](./crypto.md#cryptocreateecdhcurvename) 函数来创建。 15 | 16 | ``` javascript 17 | const crypto = require('crypto'); 18 | const assert = require('assert'); 19 | 20 | // Generate Alice's keys... 21 | const alice = crypto.createECDH('secp521r1'); 22 | const alice_key = alice.generateKeys(); 23 | 24 | // Generate Bob's keys... 25 | const bob = crypto.createECDH('secp521r1'); 26 | const bob_key = bob.generateKeys(); 27 | 28 | // Exchange and generate the secret... 29 | const alice_secret = alice.computeSecret(bob_key); 30 | const bob_secret = bob.computeSecret(alice_key); 31 | 32 | assert(alice_secret, bob_secret); 33 | // OK 34 | ``` 35 | 36 | 37 | ## ecdh.generateKeys([encoding[, format]]) 38 | 39 | 生成私有的和公共的 EC Diffie-Hellman 键值,并返回指定 `format` 和 `encoding` 的公钥。这个密钥应该转移到另一方。 40 | 41 | `format` 参数指定点编码,可以是 `'compressed'`、`'uncompressed'` 或 `'hybrid'`。如果没有指定 `format`,这个点会以 `'uncompressed'` 格式返回。 42 | 43 | `encoding` 参数可以是 `'binary'`、`'hex'` 或 `'base64'`。如果提供了 `encoding`,会返回一个字符串;否则返回一个 [Buffer](../buffer/)。 44 | 45 | 46 | ## ecdh.setPrivateKey(private_key[, encoding]) 47 | 48 | 设置一个 EC Diffie-Hellman 私钥。`encoding` 可以是 `'binary'`、`'hex'` 或 `'base64'`。如果提供了 `encoding`,`private_key` 则期望是个字符串;否则,`private_key` 期望是一个 [Buffer](../buffer/)。当 `ECDH` 对象被创建时,如果 `private_key` 指定的曲线无效,将抛出错误。在设置私钥时,还在 ECDH 对象中生成和设置了相关联的公共点(密钥)。 49 | 50 | 51 | ## ecdh.getPrivateKey([encoding]) 52 | 53 | 返回指定了 `encoding` 的 EC Diffie-Hellman 私钥,它可以是 `'binary'`、`'hex'` 或 `'base64'`。如果提供了 `encoding`,会返回一个字符串;否则返回一个 [Buffer](../buffer/)。 54 | 55 | 56 | ## ecdh.setPublicKey(public_key[, encoding]) 57 | 58 | > 稳定度:0 - 已废弃 59 | 60 | 设置一个 EC Diffie-Hellman 公钥。密钥的编码可以是 `'binary'`、`'hex'` 或 `'base64'`。如果提供了 `public_key` 则期望是个字符串;否则,期望是一个 [Buffer](../buffer/)。 61 | 62 | 请注意,通常没有理由调用此方法,因为 `ECDH` 只需要私钥和对方的公钥来计算共享密钥。通常会调用 [ecdh.generateKeys()](#ecdhgeneratekeysencoding-format) 或 [ecdh.setPrivateKey()](#ecdhsetprivatekeyprivatekey-encoding)。[ecdh.setPrivateKey()](#ecdhsetprivatekeyprivatekey-encoding) 方法尝试生成与正被设置的私钥相关联的公共点/密钥。 63 | 64 | 示例(获取共享密钥): 65 | 66 | ``` javascript 67 | const crypto = require('crypto'); 68 | const alice = crypto.createECDH('secp256k1'); 69 | const bob = crypto.createECDH('secp256k1'); 70 | 71 | // Note: This is a shortcut way to specify one of Alice's previous private 72 | // keys. It would be unwise to use such a predictable private key in a real 73 | // application. 74 | alice.setPrivateKey( 75 | crypto.createHash('sha256').update('alice', 'utf8').digest() 76 | ); 77 | 78 | // Bob uses a newly generated cryptographically strong 79 | // pseudorandom key pair bob.generateKeys(); 80 | 81 | const alice_secret = alice.computeSecret(bob.getPublicKey(), null, 'hex'); 82 | const bob_secret = bob.computeSecret(alice.getPublicKey(), null, 'hex'); 83 | 84 | // alice_secret and bob_secret should be the same shared secret value 85 | console.log(alice_secret === bob_secret); 86 | ``` 87 | 88 | 89 | ## ecdh.getPublicKey([encoding[, format]]) 90 | 91 | 返回指定了 `encoding` 和 `format` 的 EC Diffie-Hellman 公钥。 92 | 93 | `format` 参数指定点编码,可以是 `'compressed'`、`'uncompressed'` 或 `'hybrid'`。如果没有指定 `format`,这个点会以 `'uncompressed'` 格式返回。 94 | 95 | `encoding` 参数可以是 `'binary'`、`'hex'` 或 `'base64'`。如果提供了 `encoding`,会返回一个字符串;否则返回一个 [Buffer](../buffer/)。 96 | 97 | 98 | ## ecdh.computeSecret(other_public_key[, input_encoding][, output_encoding]) 99 | 100 | 使用作为对方的公钥的 `other_public_key` 计算共享密钥,并返回计算后的共享密钥。使用指定的 `input_encoding` 解释提供的密钥,并返回使用指定 `output_encoding` 编码的密钥。编码可以是 `'binary'`、`'hex'` 或 `'base64'`。如果没有提供 `input_encoding`,`other_public_key` 期望是一个 [Buffer](../buffer/)。 101 | 102 | 如果给出了 `output_encoding`,将返回一个字符串;否则,返回一个 [Buffer](../buffer/)。 -------------------------------------------------------------------------------- /http/class_http_IncomingMessage.md: -------------------------------------------------------------------------------- 1 | # http.IncomingMessage类 2 | 3 | * ['close' 事件](#close-事件) 4 | * [message.httpVersion](#messagehttpversion) 5 | * [message.url](#messageurl) 6 | * [message.socket](#messagesocket) 7 | * [message.method](#messagemethod) 8 | * [message.headers](#messageheaders) 9 | * [message.trailers](#messagetrailers) 10 | * [message.rawHeaders](#messagerawheaders) 11 | * [message.rawTrailers](#messagerawtrailers) 12 | * [message.statusCode](#messagestatuscode) 13 | * [message.statusMessage](#messagestatusmessage) 14 | * [message.setTimeout(msecs, callback)](#messagesettimeoutmsecs-callback) 15 | 16 | -------------------------------------------------- 17 | 18 | 19 | `IncomingMessage` 对象由 [http.Server](./class_http_Server.md#) 或 [http.ClientRequest](./class_http_ClientRequest.md#) 创建,并作为第一参数分别递给 `'request'` 和 `'response'` 事件。它可以用来访问响应状态,报头和数据。 20 | 21 | 它实现了[可读流](../stream/api_for_stream_implementors.md#)接口,以及下面的其他事件、方法和属性。 22 | 23 | 24 | ## 'close' 事件 25 | 26 | `function () { }` 27 | 28 | 表明基础连接已关闭。跟 `'end'` 一样,这个事件对于每个响应只会触发一次。 29 | 30 | 31 | ## message.httpVersion 32 | 33 | 在服务器请求的情况下,HTTP 版本号由客户端发送。在客户端响应的情况下,HTTP 版本由所连接到服务器决定。也许是 `'1.1'` 或 `'1.0'`。 34 | 35 | 同样,`message.httpVersionMajor` 是第一个整数,`message.httpVersionMinor` 是第二个整数。 36 | 37 | 38 | ## message.url 39 | 40 | **仅适用于从 [http.Server](./class_http_Server.md#) 获得的请求。** 41 | 42 | 请求的 URL 字符串。这仅包含实际存在的 HTTP 请求的 URL。如果请求是: 43 | 44 | ``` javascript 45 | GET /status?name=ryan HTTP/1.1\r\n 46 | Accept: text/plain\r\n 47 | \r\n 48 | ``` 49 | 50 | 那么 `request.url` 会是: 51 | 52 | ``` javascript 53 | '/status?name=ryan' 54 | ``` 55 | 56 | 如果你想将 URL 解析成其组成部分,你可以使用 `require('url').parse(request.url)`。例如: 57 | 58 | ``` bash 59 | $ node 60 | > require('url').parse('/status?name=ryan') 61 | { 62 | href: '/status?name=ryan', 63 | search: '?name=ryan', 64 | query: 'name=ryan', 65 | pathname: '/status' 66 | } 67 | ``` 68 | 69 | 如果你想从查询字符串中提取参数,你可以使用 `require('querystring').parse` 函数,或传递 `true` 作为 `require('url').parse` 的第二个参数。例如: 70 | 71 | ``` bash 72 | $ node 73 | > require('url').parse('/status?name=ryan', true) 74 | { 75 | href: '/status?name=ryan', 76 | search: '?name=ryan', 77 | query: { 78 | name: 'ryan' 79 | }, 80 | pathname: '/status' 81 | } 82 | ``` 83 | 84 | 85 | ## message.socket 86 | 87 | 与此连接相关联的 [net.Socket](../net/class_net_Socket.md#) 对象。 88 | 89 | 通过 HTTPS 的支持,使用 [request.socket.getPeerCertificate()](../tls/class_tls_TLSSocket.md#tlssocketgetpeercertificatedetailed) 获取客户端的认证信息。 90 | 91 | 92 | ## message.method 93 | 94 | **仅适用于从 [http.Server](./class_http_Server.md#) 获得的请求。** 95 | 96 | 请求方法为字符串。只读。例如:`'GET'`,`'DELETE'`。 97 | 98 | 99 | ## message.header 100 | 101 | 请求/响应头的对象。 102 | 103 | 键值对的报头名称和值。报头名称为小写。例如: 104 | 105 | ``` javascript 106 | // Prints something like: 107 | // 108 | // { 'user-agent': 'curl/7.22.0', 109 | // host: '127.0.0.1:8000', 110 | // accept: '*/*' } 111 | console.log(request.headers); 112 | ``` 113 | 114 | 原报头按以下方式根据不同的头名进行重复处理: 115 | 116 | * 重复 `age`,`authorization`,`content-length`,`content-type`,`etag`,`expires`,`from`,`host`,`if-modified-since`,`if-unmodified-since`,`last-modified`,`location`,`max-forwards`,`proxy-authorization`,`referer`,`retry-after` 或已丢弃的 `user-agent`。 117 | 118 | * `set-cookie` 始终是一个数组。重复被添加到队列。 119 | 120 | * 对于所有其他头,其值使用“,”相连。 121 | 122 | 123 | ## message.trailers 124 | 125 | 请求/响应报尾对象。只在 `'end'` 事件时填入。 126 | 127 | 128 | ## message.rawHeaders 129 | 130 | 接收到的原始请求/响应头字段列表。 131 | 132 | 注意,该键和值是在同一列表中。它*不是*一个元组列表。偶数偏移量为键,奇数偏移量为对应的值。 133 | 134 | 报头名称没有转换为小写,也没有合并重复的头。 135 | 136 | ``` javascript 137 | // Prints something like: 138 | // 139 | // [ 'user-agent', 140 | // 'this is invalid because there can be only one', 141 | // 'User-Agent', 142 | // 'curl/7.22.0', 143 | // 'Host', 144 | // '127.0.0.1:8000', 145 | // 'ACCEPT', 146 | // '*/*' ] 147 | console.log(request.rawHeaders); 148 | ``` 149 | 150 | 151 | ## message.rawTrailers 152 | 153 | 接收到的原始的请求/响应报尾的键和值。只在 `'end'` 事件时填入。 154 | 155 | 156 | ## message.statusCode 157 | 158 | **仅适用于从 [http.ClientRequest](./class_http_ClientRequest.md#) 获得响应。** 159 | 160 | 3位 HTTP 响应状态码。如,`404`。 161 | 162 | 163 | ## message.statusMessage 164 | 165 | **仅适用于从 [http.ClientRequest](./class_http_ClientRequest.md#) 获得响应。** 166 | 167 | HTTP 响应状态消息(简短的原因)。如,`OK` 或 `Internal Server Error`。 168 | 169 | 170 | ## message.setTimeout(msecs, callback) 171 | 172 | * `msecs` {Number} 173 | 174 | * `callback` {Function} 175 | 176 | 调用 `message.connection.setTimeout(msecs, callback)`。 177 | 178 | 返回 `message`。 -------------------------------------------------------------------------------- /errors/class_Error.md: -------------------------------------------------------------------------------- 1 | # Error类 2 | 3 | * [new Error(message)](#new_Error) 4 | * [Error.captureStackTrace(targetObject[, constructorOpt])](#captureStackTrace) 5 | * [Error.stackTraceLimit](#stackTraceLimit) 6 | - [error.message](#message) 7 | - [error.stack](#stack) 8 | 9 | -------------------------------------------------- 10 | 11 | 12 | 一个普通的 JavaScript `Error` 对象不会表述错误发生的具体原因。`Error` 对象会捕捉一个详细说明被实例化的 `Error` 对象在代码中的位置的“堆栈跟踪”,并可能提供对此错误的文字描述。 13 | 14 | 所有由 Node.js 产生的系统和 JavaScript 错误都继承实例化或继承自 `Error` 类。 15 | 16 | 17 |
18 | ## new Error(message) 19 | 20 | 新建一个 `Error` 实例并设置它的 `error.message` 属性以提供文本信息。如果 `message` 传的是一个对象,则会通过 `message.toString()` 生成文本信息。`error.stack` 属性会表明 `new Error()` 在代码中的位置。 21 | 堆栈跟踪是根据 [V8 的堆栈跟踪 API](https://github.com/v8/v8/wiki/Stack-Trace-API) 生成的。堆栈跟踪只会取(a)*异步代码开始执行*前或(b)`Error.stackTraceLimit` 属性给出的栈帧中的最小项。 22 | 23 | 24 |
25 | ## Error.captureStackTrace(targetObject[, constructorOpt]) 26 | 27 | 当访问调用 `Error.captureStackTrace()` 方法所返回的表示代码中的位置的字符串时,会在 `targetObject` 上创建一个 `.stack` 属性。 28 | 29 | ```javascript 30 | const myObject = {}; 31 | Error.captureStackTrace(myObject); 32 | myObject.stack // similar to `new Error().stack` 33 | ``` 34 | 35 | 堆栈跟踪的第一行会是前缀被替换成 `ErrorType: message` 的 `targetObject.toString()` 的调用结果。 36 | 37 | 可选的 `constructorOpt` 接受一个函数作为其参数。如果提供了该参数,则 `constructorOpt` 以前包括自身在内的全部栈帧都会被其生成的堆栈跟踪省略。 38 | 39 | `constructorOpt` 用在向最终用户隐藏错误生成的具体细节时非常有用。例如: 40 | 41 | ```javascript 42 | function MyError() { 43 | Error.captureStackTrace(this, MyError); 44 | } 45 | 46 | // Without passing MyError to captureStackTrace, the MyError 47 | // frame would should up in the .stack property. by passing 48 | // the constructor, we omit that frame and all frames above it. 49 | new MyError().stack 50 | ``` 51 | 52 | 53 |
54 | ## Error.stackTraceLimit 55 | 56 | `Error.stackTraceLimit` 属性用于指定堆栈跟踪所收集的栈帧数量(无论是由 `new Error().stack` 还是由 `Error.captureStackTrace(obj)` 产生的)。 57 | 58 | 默认值为 `10` ,但可以设置成任何有效 JavaScript 数值。这个修改会影响到*值被改变后*捕捉到的所有堆栈跟踪。 59 | 60 | 如果设置成一个非数值或负数,堆栈跟踪将不会捕捉任何栈帧。 61 | 62 | 63 |
64 | #### error.message 65 | 66 | 返回由 `new Error(message)` 设置的用来描述错误的字符串。这个传递给构造函数的 `message` 也将出现在 `Error` 的堆栈跟踪的第一行。然而,在 `Error` 对象创建后改变这个属性*可能不会*改变堆栈跟踪的第一行。 67 | 68 | ```javascript 69 | const err = new Error('The message'); 70 | console.log(err.message); 71 | // Prints: The message 72 | ``` 73 | 74 | 75 |
76 | #### error.stack 77 | 78 | 返回一个描述 `Error` 实例在代码中的位置的字符串。 79 | 80 | 例如: 81 | 82 | ``` 83 | Error: Things keep happening! 84 | at /home/gbusey/file.js:525:2 85 | at Frobnicator.refrobulate (/home/gbusey/business-logic.js:424:21) 86 | at Actor. (/home/gbusey/actors.js:400:8) 87 | at increaseSynergy (/home/gbusey/actors.js:701:6) 88 | ``` 89 | 90 | 第一行会被格式化为 `: ` ,并且随后跟着一系列栈帧(每一行都会以 "at " 开头)。每一帧都描述了一个代码中导致错误生成的调用点。V8 引擎会尝试显示每个函数的名称(变量名、函数名或对象的方法名),但偶尔也可能找不到一个合适的名称。如果 V8 引擎没法确定一个函数的名称,在该栈帧中只会显示仅有的位置信息。否则,在位置信息的附近将会显示已确定的函数名。 91 | 92 | 注意,这对**仅**由 JavaScript 函数产生的栈帧非常有用。例如,在自身是一个 JavaScript 函数的情况下,通过同步执行一个名为 `cheetahify` 的 C++ 插件时,代表 `cheetahify` 回调的栈帧将**不会**出现在当前的堆栈跟踪里: 93 | 94 | 95 | ```javascript 96 | const cheetahify = require('./native-binding.node'); 97 | 98 | function makeFaster() { 99 | // cheetahify *synchronously* calls speedy. 100 | cheetahify(function speedy() { 101 | throw new Error('oh no!'); 102 | }); 103 | } 104 | 105 | makeFaster(); // will throw: 106 | // /home/gbusey/file.js:6 107 | // throw new Error('oh no!'); 108 | // ^ 109 | // Error: oh no! 110 | // at speedy (/home/gbusey/file.js:6:11) 111 | // at makeFaster (/home/gbusey/file.js:5:3) 112 | // at Object. (/home/gbusey/file.js:10:1) 113 | // at Module._compile (module.js:456:26) 114 | // at Object.Module._extensions..js (module.js:474:10) 115 | // at Module.load (module.js:356:32) 116 | // at Function.Module._load (module.js:312:12) 117 | // at Function.Module.runMain (module.js:497:10) 118 | // at startup (node.js:119:16) 119 | // at node.js:906:3 120 | ``` 121 | 122 | 其中的位置信息会以下形式出现: 123 | 124 | * `native`,如果栈帧产生自 V8 引擎内部(比如,`[].forEach`)。 125 | 126 | * `plain-filename.js:line:column`,如果栈帧产生自 Node.js 内部。 127 | 128 | * `/absolute/path/to/file.js:line:column`,如果栈帧产生自用户程序或其依赖。 129 | 130 | 代表堆栈跟踪的字符串是在**访问** `error.stack` 属性时才被生成的。 131 | 132 | 堆栈跟踪捕获的栈帧的数量是由 `Error.stackTraceLimit` 或当前事件循环可用的栈帧数量中的最小值界定。 133 | 134 | 系统级的错误由已传参的 `Error` 实例产生,详见[此处](./system_errors.md#)。 -------------------------------------------------------------------------------- /vm/vm.md: -------------------------------------------------------------------------------- 1 | # 方法和属性 2 | 3 | * [vm.createContext([sandbox])](#createContext) 4 | * [vm.isContext(sandbox)](#isContext) 5 | * [vm.runInThisContext(code[, options])](#runInThisContext) 6 | * [vm.runInContext(code, contextifiedSandbox[, options])](#runInContext) 7 | * [vm.runInNewContext(code[, sandbox][, options])](#runInNewContext) 8 | * [vm.runInDebugContext(code)](#runInDebugContext) 9 | 10 | -------------------------------------------------- 11 | 12 | 13 |
14 | ## vm.createContext([sandbox]) 15 | 16 | 如果给一个 `sandbox` 的对象,则将沙箱 (sandbox) 对象 “上下文化 (contextify)” 供 [vm.runInContext](#runInContext) 或 [script.runInContext](./class_Script.md#runInContext) 调用。 以此方式运行的脚本将以 `sandbox` 作为全局对象,该对象将在保留其所有的属性的基础上拥有标准[全局对象](https://es5.github.io/#x15.1)所拥有的内置对象和函数。在由 vm 模块运行的脚本之外的地方 `sandbox` 将不会被改变。 17 | 18 | 如果没有提供沙箱对象,则返回一个新的、空的、没被上下文化的可用沙箱。 19 | 20 | 此函数可用于创建可执行多个脚本的沙箱,如,在模拟浏览器的时候可以使用该函数创建一个用于表示 `window` 全局对象的沙箱, 并将所有 `