diff --git a/locale/zh-cn/about/community.md b/locale/zh-cn/about/community.md index 28565b29a4f88..a7098a212eb54 100644 --- a/locale/zh-cn/about/community.md +++ b/locale/zh-cn/about/community.md @@ -7,13 +7,13 @@ layout: about.hbs 社区委员会(CommComm)是 Node.js 最高级别的委员会。委员会对外拥有一定的权利,其中包括: -* 社区 [布道](https://github.com/nodejs/evangelism) +* 社区[布道](https://github.com/nodejs/evangelism) * 教育倡议 * Node.js 基础的文化指导 * 社区组织拓展 * 翻译及国际化项目 * 项目审核 / 调解 -* 公共拓展以及 [出版物](https://medium.com/the-node-js-collection) +* 公共拓展以及[出版物](https://medium.com/the-node-js-collection) 参与社区委员会类型总共分为四类: @@ -28,23 +28,23 @@ layout: about.hbs 发展壮大 Node.js 社区是社区委员会的使命。当你读到这时,你其实已经是社区的一份子了 —— 同时也是 Node.js 社区的一份子。我们热爱你的帮助! -在 [nodejs/community-committee](https://github.com/nodejs/community-committee) 中,GitHub 是一个很好的开始。请查看 [标记为“首要议题”](https://github.com/nodejs/community-committee/labels/good%20first%20issue) 相关内容以便了解我们需要在哪里需要你的帮助。如果你有关于我们如何更好地鼓励和构建我们社区的建议,放心大胆地提出议题并向我们已有的工作提出 PR。或者通过我们在 GitHub 上已有的讨论中分享你的相关想法。 +在 [nodejs/community-committee](https://github.com/nodejs/community-committee) 中,GitHub 是一个很好的开始。请查看[标记为“首要议题”](https://github.com/nodejs/community-committee/labels/good%20first%20issue)相关内容以便了解我们需要在哪里需要你的帮助。如果你有关于我们如何更好地鼓励和构建我们社区的建议,放心大胆地提出议题并向我们已有的工作提出 PR。或者通过我们在 GitHub 上已有的讨论中分享你的相关想法。 你可以进一步参与我们持续构建社区的活动 —— 像本地化、布道、Node.js 意见收集和其它活动 —— 通过对 Node.js 源仓库的深入挖掘开始融入其中! -在此之前,请确认你已经细读了 [合作者指南](https://github.com/nodejs/community-committee/blob/master/governance/COLLABORATOR_GUIDE.md)。 +在此之前,请确认你已经细读了[合作者指南](https://github.com/nodejs/community-committee/blob/master/governance/COLLABORATOR_GUIDE.md)。 -如果你对以社区会员身份参与社区委员会活动感兴趣的话,你应该阅读以下 **观察者与会员** 相关章节部分。随后发出请求希望成为我们下一届社区委员会的观察者。你可以在 [此处](https://github.com/nodejs/community-committee/issues/142) 寻找到相关的内容。 +如果你对以社区会员身份参与社区委员会活动感兴趣的话,你应该阅读以下 **观察者与会员** 相关章节部分。随后发出请求希望成为我们下一届社区委员会的观察者。你可以在[此处](https://github.com/nodejs/community-committee/issues/142)寻找到相关的内容。 ## 观察者与会员 如果你对更进一步参与社区委员会以及相关项目感兴趣的话,我们鼓励你成为一个活跃的观察者,为直接成为会员而努力工作。要想成为一个会员,你必须做到: 1. 参与每周两次的会议,探讨那些标记为首要议题、会议文件以及 PR。并通过 GitHub,以贡献者或者合作者的身份凸显你的洞察力。 -2. 通过发起请求成为一个观察者。一旦作为观察者被邀请加入参与会议,我们会持续三个月跟踪记录你的参与度以符合我们的治理准则。你可以在 [此处](https://github.com/nodejs/community-committee/issues/142) 寻找到有关于此的绝好例子。 +2. 通过发起请求成为一个观察者。一旦作为观察者被邀请加入参与会议,我们会持续三个月跟踪记录你的参与度以符合我们的治理准则。你可以在[此处](https://github.com/nodejs/community-committee/issues/142) 寻找到有关于此的绝好例子。 3. 当你已经符合了三个月的最低考勤条件,且符合期望参与度,社区委员会将投票把你纳入会员。 -会员身份可以保持六个月。小组会定期询问逾期会员是否继续愿意留任。会员只需回复“留任”即可。社区委员会虽无固定大小限制,但是,希望的人数最好在九到十二人之间。你可以在 [治理准则](https://github.com/nodejs/community-committee/blob/master/GOVERNANCE.md) 中阅读更多有关会员身份的资料信息,以及其它管理信息。 +会员身份可以保持六个月。小组会定期询问逾期会员是否继续愿意留任。会员只需回复“留任”即可。社区委员会虽无固定大小限制,但是,希望的人数最好在九到十二人之间。你可以在[治理准则](https://github.com/nodejs/community-committee/blob/master/GOVERNANCE.md)中阅读更多有关会员身份的资料信息,以及其它管理信息。 定期社区委员会的会议每两个月通过变焦视频举行,然后会在 YouTube 上向公众播放。任何一个社区会员或者贡献者都可以通过 GitHub 发起请求参与下一次的会议议程。 @@ -52,6 +52,6 @@ layout: about.hbs ## 寻求协商一致的过程 -社区委员会遵循着 [寻求共识](https://en.wikipedia.org/wiki/Consensus-seeking_decision-making) 的原则来决定规划。 +社区委员会遵循着[寻求共识](https://en.wikipedia.org/wiki/Consensus-seeking_decision-making) 的原则来决定规划。 当任意一个议题将进入达成共识的阶段时,主持人会问大家“有人有不同意见吗?”作为最后的提醒,确保达成了共识而没有异议。如果实在无法达成共识但是又没有异议,那么只能采取多数投票。但是我们希望多数的决议是通过寻求共识做出的,而投票只是最后的备选方案。 diff --git a/locale/zh-cn/about/governance.md b/locale/zh-cn/about/governance.md index 8338739ec3fdc..491fdfc4ac9cb 100644 --- a/locale/zh-cn/about/governance.md +++ b/locale/zh-cn/about/governance.md @@ -7,7 +7,7 @@ layout: about.hbs ## 追求一致协商 -Node.js 项目遵循 [一致协商][] 的工作模式。 +Node.js 项目遵循[一致协商][] 的工作模式。 ## 贡献者 @@ -21,7 +21,7 @@ Node.js 项目遵循 [一致协商][] 的工作模式。 ## 最高级别的委员会 -本项目由 [技术指导委员会(TSC)][] 和 [社区委员会(CommComm)][] 共同管理。前者对于项目中高级别的技术负责指导,后者则对指导和扩展社区进行负责。 +本项目由[技术指导委员会(TSC)][]和[社区委员会(CommComm)][]共同管理。前者对于项目中高级别的技术负责指导,后者则对指导和扩展社区进行负责。 [COLLABORATOR_GUIDE.md]: https://github.com/nodejs/node/blob/master/COLLABORATOR_GUIDE.md [社区委员会(CommComm)]: https://github.com/nodejs/community-committee/blob/master/Community-Committee-Charter.md diff --git a/locale/zh-cn/about/index.md b/locale/zh-cn/about/index.md index bbe06bccbabdb..2b3e11b04df3e 100644 --- a/locale/zh-cn/about/index.md +++ b/locale/zh-cn/about/index.md @@ -25,19 +25,19 @@ server.listen(port, hostname, () => { }); ``` -这与今天使用 OS 线程的更常见并发模型形成了对比。基于线程的网络效率相对低下,使用起来非常困难。此外,Node.js 的用户不必担心死锁过程, 因为没有锁。Node 中几乎没有函数直接执行 I/O 操作,因此进程从不阻塞。由于没有任何阻塞,可伸缩系统在 Node 中开发是非常合理的。 +这与今天使用 OS 线程的更常见并发模型形成了对比。基于线程的网络效率相对低下,使用起来非常困难。此外,Node.js 的用户不必担心死锁过程,因为没有锁。Node 中几乎没有函数直接执行 I/O 操作,因此进程从不阻塞。由于没有任何阻塞,可伸缩系统在 Node 中开发是非常合理的。 -如果你对这门语言其中的一部分尚未熟悉理解,这里有一篇专门关于 [阻塞对比非阻塞][] 的文章供你参考。 +如果你对这门语言其中的一部分尚未熟悉理解,这里有一篇专门关于[阻塞对比非阻塞][]的文章供你参考。 --- -Node.js 在设计上类似于 Ruby 的 [事件机][] 或 Python 的 [Twisted][] 之类的系统。 Node.js 更深入地考虑事件模型。它呈现一个 [事件轮询][] 作为运行时构造而不是库。在其它系统中,总是有一个阻止调用来启动事件循环。 +Node.js 在设计上类似于 Ruby 的[事件机][] 或 Python 的 [Twisted][]之类的系统。 Node.js 更深入地考虑事件模型。它呈现一个[事件轮询][]作为运行时构造而不是库。在其它系统中,总是有一个阻止调用来启动事件循环。 通常 Node.js 的行为是通过在脚本开头的回调定义的,在结束时通过阻塞调用(如 `EventMachine::run()` )启动服务器。在 Node.js 中没有这样的启动-事件循环调用。Node.js 在执行输入脚本后只需输入事件循环即可。 当没有更多要执行的回调时,Node.js 退出事件循环。此行为类似于浏览器中的 JavaScript ——事件循环总是对用户不可见的。 HTTP 是 Node.js 中的一等公民。它设计的是流式和低延迟。这使得 Node.js 非常适合于 web 库或框架的基础。 -仅仅因为 Node.js 是在没有线程的情况下设计的,这并不意味着您无法利用环境中的多个内核。子进程可以通过使用我们的 [`child_process.fork()`][] API 来生成, 并且被设计为易于沟通。建立在同一接口上的是 [`cluster`][] 模块, 它允许您在进程之间共享套接字, 以便在核心上启用负载平衡。 +仅仅因为 Node.js 是在没有线程的情况下设计的,这并不意味着您无法利用环境中的多个内核。子进程可以通过使用我们的 [`child_process.fork()`][] API 来生成,并且被设计为易于沟通。建立在同一接口上的是 [`cluster`][] 模块,它允许您在进程之间共享套接字,以便在核心上启用负载平衡。 [阻塞对比非阻塞]: /zh-cn/docs/guides/blocking-vs-non-blocking/ [`child_process.fork()`]: https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options diff --git a/locale/zh-cn/about/releases.md b/locale/zh-cn/about/releases.md index f9ce3b31a4ff2..703ac68cabff0 100644 --- a/locale/zh-cn/about/releases.md +++ b/locale/zh-cn/about/releases.md @@ -20,6 +20,6 @@ schedule-footer: 日期可能会发生变化。 # 发布 主版本的 Node.js 进入 _当前版_ 将持续六个月的时间,在此期间库作者可以对其进行支持。 -六个月之后,奇数版本(诸如9、11等)将变为不支持状态,只有偶数版本(诸如10、12等)变成 _活跃LTS_ 状态,并且准备投入使用。 -_LTS_ 发布版的状态是“长期维护版”,这意味着重大的Bug将在后续的30个月内持续得到不断地修复。 -上线应该仅使用 _活跃LTS_ 或者是 _维护LTS_ 版。 +六个月之后,奇数版本(诸如9、11等)将变为不支持状态,只有偶数版本(诸如10、12等)变成 _活跃 LTS_ 状态,并且准备投入使用。 +_LTS_ 发布版的状态是“长期维护版”,这意味着重大的 Bug 将在后续的 30 个月内持续得到不断地修复。 +上线应该仅使用 _活跃 LTS_ 或者是 _维护 LTS_ 版。 diff --git a/locale/zh-cn/about/resources.md b/locale/zh-cn/about/resources.md index 94d4e3f402bc3..61414d74278f1 100644 --- a/locale/zh-cn/about/resources.md +++ b/locale/zh-cn/about/resources.md @@ -7,9 +7,9 @@ title: 商标和图像 ## 商标下载 -请查看相关 [商标政策](/zh-cn/about/trademark/) 以便了解许可范围内的 Node.js®;商标以及标记等。 +请查看相关[商标政策](/zh-cn/about/trademark/)以便了解许可范围内的 Node.js®;商标以及标记等。 -对于 Node.js 标志的可视化展示指南也在 [可视化指南](/static/documents/foundation-visual-guidelines.pdf) 有所描述。 +对于 Node.js 标志的可视化展示指南也在[可视化指南](/static/documents/foundation-visual-guidelines.pdf)有所描述。 diff --git a/locale/zh-cn/about/trademark.md b/locale/zh-cn/about/trademark.md index 63560bfdd3298..05f52e970bccb 100644 --- a/locale/zh-cn/about/trademark.md +++ b/locale/zh-cn/about/trademark.md @@ -9,6 +9,6 @@ Node.js 的商标、服务性标志,以及图像商标等都是质量、性能 与此同时,我们期望社区成员们可以随意轻松地传播 Node.js 的任何消息,并且参与 Node.js 的社区活动。请始终牢记关键点:我们已试图把政策制定得尽可能地弹性化、容易理解并且合法化。 -请阅读相关 [完整版政策](/static/documents/trademark-policy.pdf)。如果你有任何疑问,请不要犹豫并 [给我们来信](mailto:trademark@nodejs.org)。 +请阅读相关[完整版政策](/static/documents/trademark-policy.pdf)。如果你有任何疑问,请不要犹豫并[给我们来信](mailto:trademark@nodejs.org)。 -对于 Node.js 标志的可视化展示指南也在 [可视化指南](/static/documents/foundation-visual-guidelines.pdf) 中有所描述。 +对于 Node.js 标志的可视化展示指南也在[可视化指南](/static/documents/foundation-visual-guidelines.pdf) 中有所描述。 diff --git a/locale/zh-cn/about/working-groups.md b/locale/zh-cn/about/working-groups.md index 64ae159185092..a581d339a522e 100644 --- a/locale/zh-cn/about/working-groups.md +++ b/locale/zh-cn/about/working-groups.md @@ -6,7 +6,7 @@ title: 工作组 # 核心工作组 -核心工作组由 [技术指导委员会(TSC)](https://github.com/nodejs/TSC/blob/master/TSC-Charter.md) 创建。 +核心工作组由[技术指导委员会(TSC)](https://github.com/nodejs/TSC/blob/master/TSC-Charter.md)创建。 ## 现有工作组 @@ -14,7 +14,7 @@ title: 工作组 * [基准测试组](#benchmarking) * [构建组](#build) * [诊断组](#diagnostics) -* [Docker组](#docker) +* [Docker 组](#docker) * [宣传组](#evangelism) * [国际化翻译组](#i18n) * [发布组](#release) @@ -30,7 +30,7 @@ title: 工作组 * 维护 [NAN](https://github.com/nodejs/nan) Git 仓库,包含代码、议题以及文档。 * 维护 [addon-examples](https://github.com/nodejs/node-addon-examples) Git 仓库,包含代码、议题以及文档。 * 维护在 Node.js 项目中从属于 Node.js TSC 的 C++ 插件。 -* 维护在 Node.js 项目中从属于 Node.js TSC 的 文档。 +* 维护在 Node.js 项目中从属于 Node.js TSC 的文档。 * 维护 npm 中的 _nan_ 包,在合适的时候发布新版本。 * 传递有关 Node.js 和 NAN 接口的未来消息,给社区提前通知变更。 @@ -77,7 +77,7 @@ title: 工作组 * 定义并添加接口 / API 函数,在需要时允许产生转储。 * 定义并向生成的转储添加公共结构,对这些转储进行内省的工具给予支持。 -### [Docker组](https://github.com/nodejs/docker-node) +### [Docker 组](https://github.com/nodejs/docker-node) Docker 工作组的目的是为节点建立、维护和改进官方的 Docker 镜像。 @@ -169,7 +169,7 @@ Docker 工作组的目的是为节点建立、维护和改进官方的 Docker 承担职责: * 为以下情况制定及维护安全性协议与流程: - * 核心 Node.js 项目the core Node.js project + * 核心 Node.js 项目 * 由技术指导委员会(TSC)维护的其它项目。 * 与 Node 安全平台合作,将社区汇报的安全隐患相关数据作为共享协助带入到基础库中。 * 确保隐患数据以一个有效定时的方式更新。 diff --git a/locale/zh-cn/docs/es6.md b/locale/zh-cn/docs/es6.md index 24cbd78d95b5a..d89d90e20df55 100644 --- a/locale/zh-cn/docs/es6.md +++ b/locale/zh-cn/docs/es6.md @@ -13,7 +13,7 @@ Node.js 是针对 [V8](https://v8.dev/) 引擎构建的。为了与此引擎保 * **Staged**:这些是将要完成的特性,并且在 V8 团队看来并不一定稳定,需要一个 `--harmony` 标记。 * **In progress**:这些特性可以通过各自单独的 harmony 标记被激活使用。除非为了测试用途,否则绝不鼓励这样做。值得注意的是这些标记是借由 V8 引擎公开,将来或许会有潜在的变化而不会有任何免责声明或者协议。 -## 默认情况下什么特性随着 Node.js一起发布? +## 默认情况下什么特性随着 Node.js 一起发布? [node.green](https://node.green/) 提供了非常完整、几乎涵盖了不同版本的 Node.js 中所支持的 ECMAScript 特性。它基于 kangax 的兼容性对照表构建。 @@ -31,7 +31,7 @@ node --v8-options | grep "in progress" V8 团队现正在努力持续工作,他们借助 EcmaScript 5 或是更早时代的语言规范,利用转译或是本地相当的技术以提高新语言的功能特性,使之达到平衡。目前研发进度记录可以在 [six-speed](https://fhinkel.github.io/six-speed) 查询到,它会告诉你 ES2015 和 ESNext 的性能究竟如何(和本地的 ES5 同等技术相比)。 -特性优化的工作也随着 ES2015 到来,以上计划是通过 [执行计划](https://docs.google.com/document/d/1EA9EbfnydAmmU_lM8R_uEMQ-U_v4l9zulePSBkeYWmY),有一个 V8 团队在那儿收集整理相关信息,并协调需要提高性能、设计追踪问题的文稿等部门。 +特性优化的工作也随着 ES2015 到来,以上计划是通过[执行计划](https://docs.google.com/document/d/1EA9EbfnydAmmU_lM8R_uEMQ-U_v4l9zulePSBkeYWmY),有一个 V8 团队在那儿收集整理相关信息,并协调需要提高性能、设计追踪问题的文稿等部门。 ## 我有我自己的基本框架,可以利用 --harmony,所以我可以移除这个标记吗? diff --git a/locale/zh-cn/docs/guides/abi-stability.md b/locale/zh-cn/docs/guides/abi-stability.md index 3abdbd592d0aa..006f789df850b 100644 --- a/locale/zh-cn/docs/guides/abi-stability.md +++ b/locale/zh-cn/docs/guides/abi-stability.md @@ -15,7 +15,7 @@ layout: docs.hbs 保持并确保 ABI 兼容性的责任在于维护标头文件的团队,后者提供 API;在编译后使得在 ABI 中保持稳定。对头文件进行更改是可以的,但必须密切跟踪更改的性质,以确保在编译时 ABI 不会更改,从而不会导致 ABI 的现有用户与新版本不兼容。 ## ABI 在 Node.js 中的稳定性 -Node.js 提供的一些头文件是由几个独立的团队维护的。举个例子,诸如 `node.h` 和 `node_buffer.h` 是通过 Node.js 团队维护,而 `v8.h` 由 V8 团队维护,尽管它们之间的关系非常紧密,但是仍然都是独立的,并且都有自己的计划和优先级别。因此,Node.js 团队对于这些项目提供的头文件中引入的变更只有部分控制权。因此 Node.js 项目已采用 [语义版本控制](https://semver.org/)。这可确保项目提供的 ABI 将为所有次要版本和修补程序版本的 Node.js 发布一个稳定的 ABI。在实践中,这将意味着 Node.js 项目已承诺确保:针对给定的主要版本的 Node.js 加载时,Node.js 本地化插件编译将成功加载由任何 Node.js 次要或修补程序版本在其编译的主要版本中。 +Node.js 提供的一些头文件是由几个独立的团队维护的。举个例子,诸如 `node.h` 和 `node_buffer.h` 是通过 Node.js 团队维护,而 `v8.h` 由 V8 团队维护,尽管它们之间的关系非常紧密,但是仍然都是独立的,并且都有自己的计划和优先级别。因此,Node.js 团队对于这些项目提供的头文件中引入的变更只有部分控制权。因此 Node.js 项目已采用[语义版本控制](https://semver.org/)。这可确保项目提供的 ABI 将为所有次要版本和修补程序版本的 Node.js 发布一个稳定的 ABI。在实践中,这将意味着 Node.js 项目已承诺确保:针对给定的主要版本的 Node.js 加载时,Node.js 本地化插件编译将成功加载由任何 Node.js 次要或修补程序版本在其编译的主要版本中。 ## N-API 为 Node.js 装备了一个 API 而导致在多个 Node.js 主要版本之间保持稳定的 ABI 的需求已经出现。创建此类 API 的动机如下: @@ -32,7 +32,7 @@ Node.js 提供的一些头文件是由几个独立的团队维护的。举个例 本地插件开发者可以通过确保插件只使用 `node_api.h` 中定义的 API 以及在 `node_api_types.h` 中定义的数据结构和常量,利用 N-API 向前兼容性保证。由此方式,开发者通过向生产用户表明其应用程序的维护负担将增加,而不是通过添加一个纯粹由 JavaScript 编写的包,从而简化其插件的采用。 -N-API 是版本化的.因为会不时添加新的 API。与语义版本控制不同,N-API 版本控制是累积性的。也就是说,N-API 的每个版本在 semver 系统中传达与次要版本相同的含义,这意味着对 N-API 所做的所有更改都将向后兼容。此外,新的 N-API 将添加到实验标志下,以使社区有机会在生产环境中对其进行审核。实验状态意味着,尽管已注意确保新 API 不会在将来以 ABI 不兼容的方式进行修改,但在生产中尚未充分证明它是正确和有用的。 因此,在最终并入即将推出的 N-API 版本之前可能会经历 ABI 不兼容的更改。也就是说,正向兼容性保证尚未涵盖实验性的 N-API。 +N-API 是版本化的,因为会不时添加新的 API;与语义版本控制不同,N-API 版本控制是累积性的。也就是说,N-API 的每个版本在 semver 系统中传达与次要版本相同的含义,这意味着对 N-API 所做的所有更改都将向后兼容。此外,新的 N-API 将添加到实验标志下,以使社区有机会在生产环境中对其进行审核。实验状态意味着,尽管已注意确保新 API 不会在将来以 ABI 不兼容的方式进行修改,但在生产中尚未充分证明它是正确和有用的。 因此,在最终并入即将推出的 N-API 版本之前可能会经历 ABI 不兼容的更改。也就是说,正向兼容性保证尚未涵盖实验性的 N-API。 [`node_api.h`]: https://github.com/nodejs/node/blob/master/src/node_api.h [`node_api_types.h`]: https://github.com/nodejs/node/blob/master/src/node_api_types.h diff --git a/locale/zh-cn/docs/guides/anatomy-of-an-http-transaction.md b/locale/zh-cn/docs/guides/anatomy-of-an-http-transaction.md index f2d9ae9a6f66f..41c8a8540667d 100644 --- a/locale/zh-cn/docs/guides/anatomy-of-an-http-transaction.md +++ b/locale/zh-cn/docs/guides/anatomy-of-an-http-transaction.md @@ -32,7 +32,7 @@ server.on('request', (request, response) => { 实际上,为了处理请求,[`listen`][] 方法需要在 `server` 对象上被显式调用。在大多数情况下,你只要把端口号作为参数传入 `listen` 方法中,作为监听端口即可。当然也有一些其它选项,具体可以参考 [API 参考文档][]。 -## 方法, 访问地址以及请求头 +## 方法、访问地址以及请求头 当处理一个请求时,第一件事你需要做的是看一下这个方法和其访问地址,以此决定你到底采取何种合理的行为。Node 通过把这些行为属性附加到 `request` 对象上,使得我们处理起来相对而言可以轻松一些。 @@ -92,7 +92,7 @@ request.on('error', (err) => { }); ``` -当然还有一些其它的方法来 [处理错误][],诸如其它的抽象化概念和工具等。但是你总是要意识到错误的确会发生,所以你应当处理它们。 +当然还有一些其它的方法来[处理错误][],诸如其它的抽象化概念和工具等。但是你总是要意识到错误的确会发生,所以你应当处理它们。 ## 我们已经聊得那么多了 diff --git a/locale/zh-cn/docs/guides/backpressuring-in-streams.md b/locale/zh-cn/docs/guides/backpressuring-in-streams.md index 0653d42f605e0..f7193a582fbc5 100644 --- a/locale/zh-cn/docs/guides/backpressuring-in-streams.md +++ b/locale/zh-cn/docs/guides/backpressuring-in-streams.md @@ -15,12 +15,12 @@ layout: docs.hbs ## 处理数据中遇到的问题 -在一个计算机系统中,通过管道,socket 和 信号量将数据从一个进程传到另外一个进程中。在 Node.js 中,我们发明了一个类似的机制,它称为 [`Stream`][]。流太棒了!它们为 Node.js 做了太多的事情,而且内部代码库的每个角落都用到了那个模块。作为一个开发者,你也应该鼓励自己多去使用这个模块! +在一个计算机系统中,通过管道,socket 和信号量将数据从一个进程传到另外一个进程中。在 Node.js 中,我们发明了一个类似的机制,它称为 [`Stream`][]。流太棒了!它们为 Node.js 做了太多的事情,而且内部代码库的每个角落都用到了那个模块。作为一个开发者,你也应该鼓励自己多去使用这个模块! ```javascript const readline = require('readline'); -// process.stdin 和 process.stdout 都是 Stream 的实例 +// process.stdin and process.stdout are both instances of Streams. const rl = readline.createInterface({ input: process.stdin, output: process.stdout @@ -66,9 +66,9 @@ const { pipeline } = require('stream'); const fs = require('fs'); const zlib = require('zlib'); -// 使用 pipiline API 可以轻松地把数据流连接到一起,并且在整个数据流 -// 处理完毕时得到通知。下面的例子就是把一个很大的视频文件使用 pipeline -// 进行 gzip 压缩。 +// Use the pipeline API to easily pipe a series of streams +// together and get notified when the pipeline is fully done. +// A pipeline to gzip a potentially huge video file efficiently: pipeline( fs.createReadStream('The.Matrix.1080p.mkv'), @@ -116,8 +116,9 @@ async function run() { 写入磁盘的速度远比从磁盘读取数据慢得多,因此,当我们试图压缩一个文件并写入磁盘时,积压的问题也就出现了。因为写磁盘的速度不能跟上读磁盘的速度。 ```javascript -// 数据流会偷偷地说:“好了,好了!停一下,这太过分了!” -// 然后数据将会在读入侧堆积,这样写入侧才能和数据流的读入速度保持同步。 +// Secretly the stream is saying: "whoa, whoa! hang on, this is way too much!" +// Data will begin to build up on the read-side of the data buffer as +// `write` tries to keep up with the incoming data flow. inp.pipe(gzip).pipe(outputFile); ``` @@ -129,7 +130,7 @@ inp.pipe(gzip).pipe(outputFile); * 太多繁重的垃圾回收 * 内存耗尽 -以下例子中我们把 `.write()` 函数的 [返回值][] 值取出,改成 `true`,这样明显地禁止了 Node.js 核心的积压的支持。在任何引用了 'modified' 二进制库的地方,我们探讨在不适用 `return ret;` 的情况下运行 `node` 二进制代码,并用 `return true;` 取代它。 +以下例子中我们把 `.write()` 函数的[返回值][] 值取出,改成 `true`,这样明显地禁止了 Node.js 核心的积压的支持。在任何引用了 'modified' 二进制库的地方,我们探讨在不适用 `return ret;` 的情况下运行 `node` 二进制代码,并用 `return true;` 取代它。 ## 过度的垃圾收集 @@ -209,7 +210,7 @@ sys 8.79 虚拟内存占用的最大字节块消耗了 87.81 mb。 -现在改变 [`.write()`][] 方法的 [返回值][],我们得到以下结果: +现在改变 [`.write()`][] 方法的[返回值][],我们得到以下结果: ``` Without respecting the return value of .write(): @@ -241,7 +242,7 @@ sys 7.43 ## 积压是怎么处理这些问题的? -我们有不同的函数将数据从一个进程传入另外一个进程。在 Node.js 中,有一个内置函数称为 [`.pipe()`][],同样地,你们也可以使用 [其它工具包][]。最终,在这个进程的基本层面上我们有二个互不相关的组件:数据的 _源头_,和 _消费者_。 +我们有不同的函数将数据从一个进程传入另外一个进程。在 Node.js 中,有一个内置函数称为 [`.pipe()`][],同样地,你们也可以使用[其它工具包][]。最终,在这个进程的基本层面上我们有二个互不相关的组件:数据的 _源头_,和 _消费者_。 当 [`.pipe()`][] 被源调用之后,它通知消费者有数据需要传输。管道函数为事件触发建立了合适的积压封装。 @@ -325,7 +326,7 @@ Readable.pipe(Transformable).pipe(Writable); 从 [Node.js v0.10][] 开始,[`Stream`][] 类借助带有下划线一些相关函数([`._read()`][] 和 [`._write()`][]),提供了访问 [`.read()`][] 或[`.write()`][] 的能力。 -这里有一些准则文档可供参考:[实现可读的流][] 和 [实现可写的流][]。我们假设你可以把这些文章已经读过了,下个章节将做稍许的深入讲解。 +这里有一些准则文档可供参考:[实现可读的流][]和[实现可写的流][]。我们假设你可以把这些文章已经读过了,下个章节将做稍许的深入讲解。 ## 实现用户自定义流须知 @@ -337,7 +338,7 @@ Readable.pipe(Transformable).pipe(Writable); 2. 在流返回 `false` 后不要调用 `.write()` 方法,而是等待 'drain'。 3. 流在不同的 Node.js 版本和库中是有变化的。小心你的测试。 -注意:关于第三点,构建浏览器流的一个难以置信的方法是使用 [`readable-stream`][]。Rodd Vagg 曾经写过一篇 [大作][] 详细描述这个工具库。简而言之,它为 [`Readable`][] 流提供了自动可销毁降解的类型,并且支持旧版的 Node.js 和 浏览器。 +注意:关于第三点,构建浏览器流的一个难以置信的方法是使用 [`readable-stream`][]。Rodd Vagg 曾经写过一篇[大作][],详细描述这个工具库。简而言之,它为 [`Readable`][] 流提供了自动可销毁降解的类型,并且支持旧版的 Node.js 和浏览器。 ## 对于可读流的规则 @@ -350,8 +351,8 @@ Readable.pipe(Transformable).pipe(Writable); 这里有个糟糕的使用 [`.push()`][] 的例子: ```javascript -// 下面的代码是有问题的,因为它完全忽略了 push 的返回值,而这个返回值是表示 -// 目的地是否存在积压的重要信号! +// This is problematic as it completely ignores return value from push +// which may be a signal for backpressure from the destination stream! class MyReadable extends Readable { _read(size) { let chunk; @@ -365,8 +366,9 @@ class MyReadable extends Readable { 另外,从定制流之外,忽略积压简直可笑至极。在以下反例中,代码仅关注数据是否到达(通过 [`'data'` event][] 订阅): ```javascript -// 下面的代码忽略了 Node.js 内部处理积压的机制,无条件地写入数据,不管目的地的流 -// 有没有做好准备接收。 +// This ignores the backpressure mechanisms Node.js has set in place, +// and unconditionally pushes through data, regardless if the +// destination stream is ready for it or not. readable.on('data', (data) => writable.write(data) ); @@ -383,8 +385,9 @@ readable.on('data', (data) => ```javascript -// 下面的可写流是有问题的,因为 JavaScript 的异步回调机制。 -// 每个 callback 都没有返回,将会有很大的几率触发多次 callback。 +// This writable is invalid because of the async nature of JavaScript callbacks. +// Without a return statement for each callback prior to the last, +// there is a great chance multiple callbacks will be called. class MyWritable extends Writable { _write(chunk, encoding, callback) { if (chunk.toString().indexOf('a') >= 0) @@ -395,7 +398,7 @@ class MyWritable extends Writable { } } -// 更恰当的写法是下面这样: +// The proper way to write this would be: if (chunk.contains('a')) return callback(); if (chunk.contains('b')) @@ -406,7 +409,8 @@ class MyWritable extends Writable { 在实现 [`._writev()`][] 方法时还有其它一些东西值得考虑。此函数与 [`.cork()`][] 耦合,但是编写代码的时有一个容易犯的错误: ```javascript -// 这里调用了 .uncork() 两次,将会对 C++ 层产生两次调用,使 cork/uncork 机制无效。 +// Using .uncork() twice here makes two calls on the C++ layer, rendering the +// cork/uncork technique useless. ws.cork(); ws.write('hello '); ws.write('world '); @@ -417,7 +421,8 @@ ws.write('from '); ws.write('Matteo'); ws.uncork(); -// 正确的做法是在 process.nextTick() 中调用 .uncork(),这样就可以在下次事件循环中触发。 +// The correct way to write this is to utilize process.nextTick(), which fires +// on the next event loop. ws.cork(); ws.write('hello '); ws.write('world '); @@ -428,7 +433,7 @@ ws.write('from '); ws.write('Matteo'); process.nextTick(doUncork, ws); -// 作为一个全局函数 +// As a global function. function doUncork(stream) { stream.uncork(); } diff --git a/locale/zh-cn/docs/guides/blocking-vs-non-blocking.md b/locale/zh-cn/docs/guides/blocking-vs-non-blocking.md index 27defecdf7bba..a5356c08d361a 100644 --- a/locale/zh-cn/docs/guides/blocking-vs-non-blocking.md +++ b/locale/zh-cn/docs/guides/blocking-vs-non-blocking.md @@ -11,9 +11,9 @@ layout: docs.hbs ## 阻塞 -**阻塞** 是指在 Node.js 程序中,其它 JavaScript 语句的执行,必须等待一个非 JavaScript 操作完成。这是因为当 **阻塞** 发生时,事件循环无法继续运行JavaScript。 +**阻塞** 是指在 Node.js 程序中,其它 JavaScript 语句的执行,必须等待一个非 JavaScript 操作完成。这是因为当 **阻塞** 发生时,事件循环无法继续运行 JavaScript。 -在 Node.js 中,JavaScript 由于执行 CPU 密集型操作,而不是等待一个非 JavaScript 操作(例如I/O)而表现不佳,通常不被称为 **阻塞**。在 Node.js 标准库中使用 libuv 的同步方法是最常用的 **阻塞** 操作。原生模块中也有 **阻塞** 方法。 +在 Node.js 中,JavaScript 由于执行 CPU 密集型操作,而不是等待一个非 JavaScript 操作(例如 I/O)而表现不佳,通常不被称为 **阻塞**。在 Node.js 标准库中使用 libuv 的同步方法是最常用的 **阻塞** 操作。原生模块中也有 **阻塞** 方法。 在 Node.js 标准库中的所有 I/O 方法都提供异步版本,**非阻塞**,并且接受回调函数。某些方法也有对应的 **阻塞** 版本,名字以 `Sync` 结尾。 @@ -25,7 +25,7 @@ layout: docs.hbs ```js const fs = require('fs'); -const data = fs.readFileSync('/file.md'); // 在这里阻塞直到文件被读取 +const data = fs.readFileSync('/file.md'); // blocks here until file is read ``` 这是一个等同的 **异步** 示例: @@ -43,9 +43,9 @@ fs.readFile('/file.md', (err, data) => { ```js const fs = require('fs'); -const data = fs.readFileSync('/file.md'); // 在这里阻塞直到文件被读取 +const data = fs.readFileSync('/file.md'); // blocks here until file is read console.log(data); -moreWork(); // 在console.log之后执行 +moreWork(); // will run after console.log ``` 这是一个类似但不等同的异步示例: @@ -56,7 +56,7 @@ fs.readFile('/file.md', (err, data) => { if (err) throw err; console.log(data); }); -moreWork(); // 在console.log之前执行 +moreWork(); // will run before console.log ``` 在上述第一个例子中, `console.log` 将在 `moreWork()` 之前被调用。在第二个例子中, `fs.readFile()` 是 **非阻塞** 的,所以 JavaScript 执行可以继续, `moreWork()` 将被首先调用。在不等待文件读取完成的情况下运行 `moreWork()` 的能力是一个可以提高吞吐量的关键设计选择。 diff --git a/locale/zh-cn/docs/guides/buffer-constructor-deprecation.md b/locale/zh-cn/docs/guides/buffer-constructor-deprecation.md index cb8c18c9ef991..18bcd19103481 100644 --- a/locale/zh-cn/docs/guides/buffer-constructor-deprecation.md +++ b/locale/zh-cn/docs/guides/buffer-constructor-deprecation.md @@ -48,16 +48,15 @@ $ node example.js ### 在使用 `linter` 的代码中找出一些问题 -ESLint 规则 [不使用缓存构造函数](https://eslint.org/docs/rules/no-buffer-constructor) -或 [node/ 无废除的 Api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) 也会寻找到使用 `Buffer()` 废弃的函数。 这些规则预先已经包含了。 +ESLint 规则[不使用缓存构造函数](https://eslint.org/docs/rules/no-buffer-constructor)或 [node/ 无废除的 Api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) 也会寻找到使用 `Buffer()` 废弃的函数。 这些规则预先已经包含了。 -不过这存在一个劣势,举个例子,当 `Buffer` 被 polyfill重写的时候,它不保证一直[正常工作](https://github.com/chalker/safer-buffer#why-not-safe-buffer)。所以推荐使用此方法和其它如上描述的方法在一起使用。 +不过这存在一个劣势,举个例子,当 `Buffer` 被 polyfill 重写的时候,它不保证一直[正常工作](https://github.com/chalker/safer-buffer#why-not-safe-buffer)。所以推荐使用此方法和其它如上描述的方法在一起使用。 ## 变化 1: 在 Node.js ≤ 4.4.x 和 5.0.0 — 5.9.x 版本中不支持 这是现在的一个推荐的解决方案,暗示仅有极小的成本。 -Node.js 5.x 发行自 2016 年就不再支持,而 4.x 版本 发行线支持到 2018 年 4 月就寿终正寝了(→ [计划表](https://github.com/nodejs/Release#release-schedule))。这意味着这些版本 *不会* 接受任何更新,即便有安全问题也不会被修复,所以如果可能,我们不应使用这些版本。 +Node.js 5.x 发行自 2016 年就不再支持,而 4.x 版本发行线支持到 2018 年 4 月就寿终正寝了(→ [计划表](https://github.com/nodejs/Release#release-schedule))。这意味着这些版本 *不会* 接受任何更新,即便有安全问题也不会被修复,所以如果可能,我们不应使用这些版本。 在这种情况下,你应该把全部的 `new Buffer()` 或 `Buffer()` 更改为 `Buffer.alloc()` 或 `Buffer.from()`,规则如下: @@ -68,19 +67,18 @@ Node.js 5.x 发行自 2016 年就不再支持,而 4.x 版本 发行线支持 注意:`Buffer.alloc()` 在当前的 Node.js 版本上 _快于_ `new Buffer(size).fill(0)`,后者是当你确认需要用 0 对整个缓存进行初始化。 -启用 ESLint 检查规则 [不使用缓存构造函数](https://eslint.org/docs/rules/no-buffer-constructor) -或[node/ 无废除的 Api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) 时,也会建议避免使用不安全的 `Buffer` 函数。 +启用 ESLint 检查规则[不使用缓存构造函数](https://eslint.org/docs/rules/no-buffer-constructor)或 [node/ 无废除的 Api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) 时,也会建议避免使用不安全的 `Buffer` 函数。 同样我们还有 [JSCodeshift codemod](https://github.com/joyeecheung/node-dep-codemod#dep005),它可以把 `Buffer` 构造函数的地方自动替换成 `Buffer.alloc()` 或 `Buffer.from()`。注意目前它只会工作在参数是文本型,或者带有两个参数的构造函数的情况下。 -_如果你目前支持那些旧版本的 Node.js,并且抛弃对它们的支持又不可能的情况下,或者你需要支持你包中的旧版本情况下,请考虑使用 [版本 2](#variant-2),或者 [版本 3](#variant-3)。这样人们可以在使用这些旧版本情况下照样修复这些安全问题。那样的话,这些由不安全的 `Buffer` 所引发的问题会被你彻底根除,你的用户也不用在你运行 Node.js 10 的时候观察你的运行时废弃警告。_ +_如果你目前支持那些旧版本的 Node.js,并且抛弃对它们的支持又不可能的情况下,或者你需要支持你包中的旧版本情况下,请考虑使用[版本 2](#variant-2),或者[版本 3](#variant-3)。这样人们可以在使用这些旧版本情况下照样修复这些安全问题。那样的话,这些由不安全的 `Buffer` 所引发的问题会被你彻底根除,你的用户也不用在你运行 Node.js 10 的时候观察你的运行时废弃警告。_ ## 变化 2: 使用替换库 存在着三种替换库: * **[更安全的缓存](https://www.npmjs.com/package/safer-buffer)** 是整个用来替换 `Buffer` 函数的方法。当你在使用 `new Buffer()` 的时候,将会 _抛出_ 异常。 - 和 [变化 1](#版本-1) 中一样,你会得到详细同样的步骤。不过请用 `const Buffer = require('safer-buffer').Buffer` 在你所有文件中对 `Buffer` 函数进行替换。 + 和[变化 1](#版本-1) 中一样,你会得到详细同样的步骤。不过请用 `const Buffer = require('safer-buffer').Buffer` 在你所有文件中对 `Buffer` 函数进行替换。 请不要使用旧版本的 `new Buffer()` 函数,在添加上面的行的任何文件中,使用 `new Buffer()` 会 _抛出_ 异常。 @@ -98,7 +96,7 @@ _如果你目前支持那些旧版本的 Node.js,并且抛弃对它们的支 注意,在任意一种情况下,手动移除你代码中所有关于 `Buffer` 的调用非常重要——仅在 `safe-buffer` 中抛出警告不解决问题,它只是为新的 API 提供了一种替换而已。我亲眼见过人们犯过这类错误。 -启用 ESLint 规则 [不使用缓存构造函数](https://eslint.org/docs/rules/no-buffer-constructor) +启用 ESLint 规则[不使用缓存构造函数](https://eslint.org/docs/rules/no-buffer-constructor) 或是 [node/ 无废除的 Api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) 是推荐的。 _如果你抛弃了对 Node.js 版本小于 4.5.0 的支持,请不要忘记把替代库也一起去掉。_ @@ -135,7 +133,7 @@ if (Buffer.from && Buffer.from !== Uint8Array.from) { `encoding` 为可选参数。 -注意在 `new Buffer()` 前的 `typeof notNumber` 检测必不可少(对于 `notNumber` 参数不是硬编码的情况下),并且 _不会引发 `Buffer` 构造函数废弃的警报_——这就是 _为什么_ 说 `Buffer` 构造函数被废弃的原因。缺少此类型检测的生态系统引发过不计其数的安全事故——如脏用户的某些输入,在 `Buffer(arg)` 可能会意外终止,这会导致从DoS攻击到从进程内存向攻击者泄露敏感信息范围内一系列问题。 +注意在 `new Buffer()` 前的 `typeof notNumber` 检测必不可少(对于 `notNumber` 参数不是硬编码的情况下),并且 _不会引发 `Buffer` 构造函数废弃的警报_——这就是 _为什么_ 说 `Buffer` 构造函数被废弃的原因。缺少此类型检测的生态系统引发过不计其数的安全事故——如脏用户的某些输入,在 `Buffer(arg)` 可能会意外终止,这会导致从 DoS 攻击到从进程内存向攻击者泄露敏感信息范围内一系列问题。 当 `notNumber` 被硬编码(如文本型 `"abc"` 或者 `[0,1,2]`), `typeof` 类型检查可以被忽略。 @@ -182,7 +180,7 @@ _注意,当你不用 0 去填充缓存,此问题同样发生在 `new Buffer( `Buffer` 构造函数可以用不同方式创建缓存: * `new Buffer(42)` 创建一个 42 个字节的 `缓存`。在 Node.js 8 之前,该缓存考虑性能,它包含 *随机内存*,而这可能包括任何数据,从编码的源码到密码,以及加密秘钥等。 -* `new Buffer('abc')` 创建一个 UTF-8 编码的字符串 `'abc'`。第二个参数可以指定用何种编码:举一个例子,`new Buffer(string, 'base64')` 可用于将Base64字符串转换为原始字符串表示的字节序列。 +* `new Buffer('abc')` 创建一个 UTF-8 编码的字符串 `'abc'`。第二个参数可以指定用何种编码:举一个例子,`new Buffer(string, 'base64')` 可用于将 Base64 字符串转换为原始字符串表示的字节序列。 * 除此之外,还有一些其它参数的组合。 这意味着在代码中诸如 `var buffer = new Buffer(foo);`,当你不知道 `foo` 是什么类型,想要知道生成的缓存里边到底存了什么内容几乎是不可能的。 diff --git a/locale/zh-cn/docs/guides/debugging-getting-started.md b/locale/zh-cn/docs/guides/debugging-getting-started.md index f8a76bfff2fba..f2c62403f45de 100644 --- a/locale/zh-cn/docs/guides/debugging-getting-started.md +++ b/locale/zh-cn/docs/guides/debugging-getting-started.md @@ -44,7 +44,7 @@ layout: docs.hbs ### [Node 监视器](https://github.com/nodejs/node-inspect) -* 由 Node.js 基础库,使用 [检查器协议][] 支持的 CLI 调试器。 +* 由 Node.js 基础库,使用[检查器协议][] 支持的 CLI 调试器。 * 和 Node 绑定在一起的版本,并且可以使用 `node inspect myscript.js`。 * 最新的版本同样可以单独通过(例如 `npm install -g node-inspect`)方式安装,并使用 `node-inspect myscript.js`。 @@ -178,13 +178,11 @@ V8 调试协议再也不维护或是归档了。 ### [内置调试器](https://nodejs.org/dist/latest-v6.x/docs/api/debugger.html) -在 Node.js 内置命令行调试器中 用 `node debug script_name.js` 启动你的脚本。你的脚本就在 Node 另外一个进程中随着 `--debug-brk` 启动了起来,并且初始化的 Node 进程运行 `_debugger.js` 脚本连接上你的目标。 +在 Node.js 内置命令行调试器中用 `node debug script_name.js` 启动你的脚本。你的脚本就在 Node 另外一个进程中随着 `--debug-brk` 启动了起来,并且初始化的 Node 进程运行 `_debugger.js` 脚本连接上你的目标。 ### [node 监视器](https://github.com/node-inspector/node-inspector) 用 Chrome 开发工具,通过 Node.js 的中间进程把 Chromium 中的检查器协议转换成 V8 调试器协议进行程序调试。 - - [检查器协议]: https://chromedevtools.github.io/debugger-protocol-viewer/v8/ [UUID]: https://tools.ietf.org/html/rfc4122 diff --git a/locale/zh-cn/docs/guides/diagnostics-flamegraph.md b/locale/zh-cn/docs/guides/diagnostics-flamegraph.md index b7b5a97b4f276..460f6faf8b6a4 100644 --- a/locale/zh-cn/docs/guides/diagnostics-flamegraph.md +++ b/locale/zh-cn/docs/guides/diagnostics-flamegraph.md @@ -44,7 +44,7 @@ layout: docs.hbs 现在你可以使用你最喜爱的浏览器打开火焰图文件,然后观察其燃烧状况。此图是带色编码的,因此你首先应该关注饱和度最深的橘色条。这些最有可能意味着你的 CPU 运行复杂函数消耗的状况。 -值得一提的是:如果你点击火焰图的一个元素, 它周围相关的元素将被放大,并将显示在图形的上方。 +值得一提的是:如果你点击火焰图的一个元素,它周围相关的元素将被放大,并将显示在图形的上方。 ### 使用 `perf` 对一个运行的进程采样 @@ -58,7 +58,7 @@ perf record -F99 -p `pgrep -n node` -g -- sleep 3 为什么 `-F`(采样频率)要被设置成 99?这是有默认原因的,当然你如果愿意可以任意设置。`-F99` 告诉 pref 每秒采样 99 个样本,目的是为了更精确地提高数值。越是低的数值意味着产出越是低的输出,相伴的也就是越是低精度的结果。你需要的精度取决于你的 CPU 运行多长时间的密集型函数。如果你正在寻找一个明显的减速的原因,那么 99 帧每秒应该是足够的。 -当你得到了那 3 秒 pref 生成的记录,请用以上步骤的最后 2 步 处理生成火焰图。 +当你得到了那 3 秒 pref 生成的记录,请用以上步骤的最后 2 步处理生成火焰图。 ### 过滤掉 Node.js 的内置函数 diff --git a/locale/zh-cn/docs/guides/dont-block-the-event-loop.md b/locale/zh-cn/docs/guides/dont-block-the-event-loop.md index b4bf372d3c4a9..eadf18c345eaa 100644 --- a/locale/zh-cn/docs/guides/dont-block-the-event-loop.md +++ b/locale/zh-cn/docs/guides/dont-block-the-event-loop.md @@ -12,7 +12,7 @@ layout: docs.hbs 文章中如有涉及到不同操作系统的细节,仅以 Linux 系统为代表。 ## 概述 -Node.js 通过事件循环机制(初始化和回调)的方式运行 JavaScript 代码,并且提供了一个线程池处理诸如 文件 I/O 等高成本的任务。 +Node.js 通过事件循环机制(初始化和回调)的方式运行 JavaScript 代码,并且提供了一个线程池处理诸如文件 I/O 等高成本的任务。 Node 的伸缩性非常好,某些场景下它甚至比类似 Apache 等更重量级的解决方案表现更优异。 Node 可伸缩性的秘诀在于它仅使用了极少数的线程就可以处理大量客户端连接。 如果 Node 只需占用很少的线程,那么它就可以将更多的系统 CPU 时间和内存花费在客户端任务而不是线程的空间和时间消耗上(内存,上下文切换)。 @@ -32,7 +32,7 @@ Node 是用很少量的线程来处理大量客户端请求的。 这里给出两个不能阻塞事件轮询线程和工作线程的理由: 1. 性能:如果你在任意类型的线程上频繁处理繁重的任务,那么你的服务器的 *吞吐量*(请求/秒)将面临严峻考验。 -2. 安全性:如果对于特定的输入,你的某种类型的线程可能会被阻塞,那么恶意攻击者可以通过构造类似这样的“恶意输入”,故意让你的线程阻塞,然后使其它客户端请求得不到处理。这就是 [拒绝服务攻击](https://en.wikipedia.org/wiki/Denial-of-service_attack)。 +2. 安全性:如果对于特定的输入,你的某种类型的线程可能会被阻塞,那么恶意攻击者可以通过构造类似这样的“恶意输入”,故意让你的线程阻塞,然后使其它客户端请求得不到处理。这就是[拒绝服务攻击](https://en.wikipedia.org/wiki/Denial-of-service_attack)。 ## 对 Node 的快速回顾 @@ -75,7 +75,7 @@ Node 模块中有如下这些 API 用到了工作线程池: 而事实上,事件轮询线程本身并不维护队列,它持有一堆要求操作系统使用诸如 [epoll](http://man7.org/linux/man-pages/man7/epoll.7.html) (Linux),[kqueue](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/FSEvents_ProgGuide/KernelQueues/KernelQueues.html) (OSX),event ports (Solaris) 或者 [IOCP](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198.aspx) (Windows) 等机制去监听的文件描述符。 这些文件描述符可能代表一个网络套接字,一个监听的文件等等。 当操作系统确定某个文件的描述符发生变化,事件轮询线程将把它转换成合适的事件,然后触发与该事件对应的回调函数。 -你可以通过 [这里](https://www.youtube.com/watch?v=P9csgxBgaZ8) 学习到更多有关这个过程的知识。 +你可以通过[这里](https://www.youtube.com/watch?v=P9csgxBgaZ8) 学习到更多有关这个过程的知识。 相对而言,工作线程池则使用一个真实的队列,里边装的都是要被处理的任务。 一个工作线程从这个队列中取出一个任务,开始处理它。当完成之后这个工作线程向事件循环线程中发出一个“至少有一个任务完成了”的消息。 @@ -154,7 +154,7 @@ Node 使用谷歌的 V8 引擎处理 JavaScript,对于大部分操作确实很 然后你可以评估此回调函数的最糟糕执行时间,根据你的业务场景决定此运行时间是否可以接受。 ### 阻塞事件轮询:REDOS -一个灾难性地阻塞事件轮询的常见错误是使用“有漏洞”的 [正则表达式](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)。 +一个灾难性地阻塞事件轮询的常见错误是使用“有漏洞”的[正则表达式](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)。 #### 避免易受攻击的正则表达式 一个正则表达式是一定的规则去尝试匹配一个输入的字符串。 @@ -216,7 +216,7 @@ app.get('/redos-me', (req, res) => { 但注意,RE2 对 Node 正则表达式不是 100% 兼容,所以如果你想用 node-re2 模块来处理你的正则表达式的话,请检仔细查你的表达式。 这里尤其值得提醒的是,一些特殊的复杂正则表达式不被 node-re2 支持。 -如果你想匹配一些较为“明显”的东西,如网络路径或者是文件路径,请在 [正则表达式库](http://www.regexlib.com) 中寻找到对应例子,或者使用一个 npm 的模块,如 [ip-regex](https://www.npmjs.com/package/ip-regex)。 +如果你想匹配一些较为“明显”的东西,如网络路径或者是文件路径,请在[正则表达式库](http://www.regexlib.com) 中寻找到对应例子,或者使用一个 npm 的模块,如 [ip-regex](https://www.npmjs.com/package/ip-regex)。 ### 阻塞事件轮询:Node 的核心模块 一些 Node 的核心模块有同步的高开销的 API 方法,包含: @@ -262,7 +262,7 @@ var niter = 20; var before, str, pos, res, took; for (var i = 0; i < niter; i++) { - obj = { obj1: obj, obj2: obj }; // 每个循环里面将对象 size 加倍 + obj = { obj1: obj, obj2: obj }; // Doubles in size each iter } before = process.hrtime(); @@ -363,7 +363,7 @@ asyncAvg(n, function(avg){ ##### 一些关于分流的建议 您可能希望区分 CPU 密集型和 I/O 密集型任务,因为它们具有明显不同的特性。 -CPU 密集型任务只有在该 Worker 线程被调度到时候才得到执行机会,并且必须将该任务分配到机器的某一个 [逻辑核心](https://nodejs.org/api/os.html#os_os_cpus)中。 +CPU 密集型任务只有在该 Worker 线程被调度到时候才得到执行机会,并且必须将该任务分配到机器的某一个[逻辑核心](https://nodejs.org/api/os.html#os_os_cpus)中。 如果你的机器有 4 个逻辑核心和 5 个工作线程,那这些工作线程中的某一个则无法得到执行。 因此,您实质上只是在为该工作线程白白支付开销(内存和调度开销),却无法得到任何返回。 @@ -372,7 +372,7 @@ I/O 密集型任务通常包括查询外部服务提供程序(DNS、文件系 当 I/O 密集型任务的工作线程正在等待其响应时,它没有其它工作可做,并且可以被操作系统重新调度,从而使另一个 Worker 有机会提交它的任务。 因此,*即使关联的线程并没有被保持,I/O 密集型任务也可以持续运行*。 像数据库和文件系统这样的外部服务提供程序已经经过高度优化,可以同时处理许多并发的请求。 -例如,文件系统会检查一大组并发等待的写入和读取请求,以合并冲突更新并以最佳顺序读取文件(请参阅 [这些幻灯片](http://researcher.ibm.com/researcher/files/il-AVISHAY/01-block_io-v1.3.pdf))。 +例如,文件系统会检查一大组并发等待的写入和读取请求,以合并冲突更新并以最佳顺序读取文件(请参阅[这些幻灯片](http://researcher.ibm.com/researcher/files/il-AVISHAY/01-block_io-v1.3.pdf))。 如果只依赖一个工作线程池(例如 Node 工作池),则 CPU 密集和 I/O 密集的任务的不同特效性可能会损害应用程序的性能。 @@ -410,11 +410,11 @@ Node 由 `k` 个工作线程组成了工作线程池。 #### 动态执行时间示例: 长时间运行的文件系统读取 假设您的服务器必须读取文件来处理某些客户端请求。 -在了解 Node 的 [文件系统](https://nodejs.org/api/fs.html) 的 API 之后,您选择使用 `fs.readFile()` 进行简单操作。 +在了解 Node 的[文件系统](https://nodejs.org/api/fs.html)的 API 之后,您选择使用 `fs.readFile()` 进行简单操作。 但是,`fs.readFile()` 是([当前](https://github.com/nodejs/node/pull/17054))未拆分任务的:它提交一个 `fs.read()` 任务来读取整个文件。 如果您为某些用户读取较短的文件,并为其它人读取较长的文件,`fs.readFile()` 可能会在任务长度上引入显著的变化,从而损害工作线程池吞吐量。 -对于最坏的情况,假设攻击者可以促使您的服务器读取 *任意* 文件(这是一个 [目录遍历漏洞](https://www.owasp.org/index.php/Path_Traversal))。 +对于最坏的情况,假设攻击者可以促使您的服务器读取 *任意* 文件(这是一个[目录遍历漏洞](https://www.owasp.org/index.php/Path_Traversal))。 如果您的服务器运行的是 Linux,攻击者可以命名一个非常慢的文件:[`/dev/random`](http://man7.org/linux/man-pages/man4/random.4.html)。 对于所有实际的目的,`/dev/random` 是无限缓慢的;每个工作线程都被要求读取 `/dev/random`,这样下去将永远不会完成这项任务。 然后,攻击者提交 `k` 个请求,每一个被分配给一个工作线程,则其它需要使用工作线程的客户端请求将得不到执行机会。 diff --git a/locale/zh-cn/docs/guides/event-loop-timers-and-nexttick.md b/locale/zh-cn/docs/guides/event-loop-timers-and-nexttick.md index 8c10b838059ea..f8f3f5e7247d3 100644 --- a/locale/zh-cn/docs/guides/event-loop-timers-and-nexttick.md +++ b/locale/zh-cn/docs/guides/event-loop-timers-and-nexttick.md @@ -192,15 +192,15 @@ immediate timeout ``` -使用 `setImmediate()` 相对于`setTimeout()` 的主要优势是,如果`setImmediate()`是在I/O周期内被调度的,那它将会在其中任何的定时器之前执行,跟这里存在多少个定时器无关 +使用 `setImmediate()` 相对于`setTimeout()` 的主要优势是,如果`setImmediate()`是在 I/O 周期内被调度的,那它将会在其中任何的定时器之前执行,跟这里存在多少个定时器无关 ## `process.nextTick()` ### 理解 `process.nextTick()` -您可能已经注意到 `process.nextTick()` 在图示中没有显示,即使它是异步 API 的一部分。这是因为 `process.nextTick()` 从技术上讲不是事件循环的一部分。相反,它都将在当前操作完成后处理 `nextTickQueue`, 而不管事件循环的当前阶段如何。这里的一个*操作*被视作为一个从 底层C/C++ 处理器开始过渡,并且处理需要执行的 JavaScript 代码。 +您可能已经注意到 `process.nextTick()` 在图示中没有显示,即使它是异步 API 的一部分。这是因为 `process.nextTick()` 从技术上讲不是事件循环的一部分。相反,它都将在当前操作完成后处理 `nextTickQueue`, 而不管事件循环的当前阶段如何。这里的一个*操作*被视作为一个从底层 C/C++ 处理器开始过渡,并且处理需要执行的 JavaScript 代码。 -回顾我们的图示,任何时候在给定的阶段中调用 `process.nextTick()`,所有传递到 `process.nextTick()` 的回调将在事件循环继续之前解析。这可能会造成一些糟糕的情况, 因为**它允许您通过递归 `process.nextTick()`调用来“饿死”您的 I/O**,阻止事件循环到达 **轮询** 阶段。 +回顾我们的图示,任何时候在给定的阶段中调用 `process.nextTick()`,所有传递到 `process.nextTick()` 的回调将在事件循环继续之前解析。这可能会造成一些糟糕的情况,因为**它允许您通过递归 `process.nextTick()`调用来“饿死”您的 I/O**,阻止事件循环到达 **轮询** 阶段。 ### 为什么会允许这样? @@ -295,7 +295,7 @@ server.listen(8080); server.on('listening', () => { }); ``` -假设 `listen()` 在事件循环开始时运行,但listening的回调被放置在 `setImmediate()` 中。除非传递过主机名,才会立即绑定到端口。为使事件循环继续进行,它必须命中 **轮询** 阶段,这意味着有可能已经接收了一个连接,并在侦听事件之前触发了连接事件。 +假设 `listen()` 在事件循环开始时运行,但 listening 的回调被放置在 `setImmediate()` 中。除非传递过主机名,才会立即绑定到端口。为使事件循环继续进行,它必须命中 **轮询** 阶段,这意味着有可能已经接收了一个连接,并在侦听事件之前触发了连接事件。 另一个示例运行的函数构造函数是从 `EventEmitter` 继承的,它想调用构造函数: diff --git a/locale/zh-cn/docs/guides/index.md b/locale/zh-cn/docs/guides/index.md index 691a282ebed77..e74e0668b3ec8 100644 --- a/locale/zh-cn/docs/guides/index.md +++ b/locale/zh-cn/docs/guides/index.md @@ -17,7 +17,7 @@ layout: docs.hbs ## Node.js 核心概念 * [阻塞对比非阻塞一览](/zh-cn/docs/guides/blocking-vs-non-blocking/) -* [Node.js 事件轮询,定时器 和 process.nextTick()](/zh-cn/docs/guides/event-loop-timers-and-nexttick/) +* [Node.js 事件轮询,定时器和 process.nextTick()](/zh-cn/docs/guides/event-loop-timers-and-nexttick/) * [不要阻塞你的事件轮询(或是工作池)](/zh-cn/docs/guides/dont-block-the-event-loop/) * [Node.js 中的定时器](/zh-cn/docs/guides/timers-in-node/) diff --git a/locale/zh-cn/docs/guides/nodejs-docker-webapp.md b/locale/zh-cn/docs/guides/nodejs-docker-webapp.md index 9b5fcc6bb3aff..5a1de2fe43252 100644 --- a/locale/zh-cn/docs/guides/nodejs-docker-webapp.md +++ b/locale/zh-cn/docs/guides/nodejs-docker-webapp.md @@ -92,7 +92,7 @@ RUN npm install # RUN npm ci --only=production ``` -请注意,我们只是拷贝了 `package.json` 文件而非整个工作目录。这允许我们利用缓存 Docker 层的优势。bitJudo 对此有一个很好的解释,请 [见此](http://bitjudo.com/blog/2014/03/13/building-efficient-dockerfiles-node-dot-js/)。 +请注意,我们只是拷贝了 `package.json` 文件而非整个工作目录。这允许我们利用缓存 Docker 层的优势。bitJudo 对此有一个很好的解释,请[见此](http://bitjudo.com/blog/2014/03/13/building-efficient-dockerfiles-node-dot-js/)。 进一步说,对于生产环境而言,注释中提及的 `npm ci` 命令协助提供了一个更快、可靠、可再生的构建环境。欲知详情,可以参考[此处](https://blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable)。 在 Docker 镜像中使用 `COPY` 命令绑定你的应用程序: diff --git a/locale/zh-cn/docs/guides/simple-profiling.md b/locale/zh-cn/docs/guides/simple-profiling.md index 727558f6a537e..830b6ab1ca332 100644 --- a/locale/zh-cn/docs/guides/simple-profiling.md +++ b/locale/zh-cn/docs/guides/simple-profiling.md @@ -111,13 +111,13 @@ Percentage of the requests served within a certain time (ms) 由于我们使用了 `--prof` 选项运行应用程序,因此在与应用程序的本地运行相同的目录中生成了一个刻度文件。它应该有形式 `isolate-0xnnnnnnnnnnnn-v8.log` (其中 `n` 为数字)。 -为了使这个文件有意义,我们需要使用与 Node.js 捆绑在一起的刻度处理器。要运行处理器, 请使用 `--prof-process` 标志: +为了使这个文件有意义,我们需要使用与 Node.js 捆绑在一起的刻度处理器。要运行处理器,请使用 `--prof-process` 标志: ``` node --prof-process isolate-0xnnnnnnnnnnnn-v8.log > processed.txt ``` -在您最喜欢的文本编辑器中打开 processed.txt 将给您提供一些不同类型的信息。该文件被分解成部分,然后再次被语言分解。首先, 我们看一下摘要部分: +在您最喜欢的文本编辑器中打开 processed.txt 将给您提供一些不同类型的信息。该文件被分解成部分,然后再次被语言分解。首先,我们看一下摘要部分: ``` [Summary]: @@ -129,7 +129,7 @@ node --prof-process isolate-0xnnnnnnnnnnnn-v8.log > processed.txt 215 0.6% Unaccounted ``` -这告诉我们:收集到的所有样本中有 97% 是在 C++ 代码中进行的。当查看处理的输出的其它部分时,我们应该最注意 C++ 中所做的工作(而不是 JavaScript)。考虑到这一点,我们接下来会找到 [C++] 部分, 其中包含有关 C++ 函数占用最多 CPU 时间的信息,然后查看一下: +这告诉我们:收集到的所有样本中有 97% 是在 C++ 代码中进行的。当查看处理的输出的其它部分时,我们应该最注意 C++ 中所做的工作(而不是 JavaScript)。考虑到这一点,我们接下来会找到 [C++] 部分,其中包含有关 C++ 函数占用最多 CPU 时间的信息,然后查看一下: ``` [C++]: @@ -139,7 +139,7 @@ node --prof-process isolate-0xnnnnnnnnnnnn-v8.log > processed.txt 3165 8.4% 8.6% _malloc_zone_malloc ``` -我们看到,前 3 个条目占了程序占用的 CPU 时间的 72.1%。从这个输出中,我们立即看到至少 51.8% 的 CPU 时间被称为 PBKDF2 的函数占用。它与用户密码中的哈希生成相对应。然而,较低的两个条目的因素是如何进入我们的应用程序(或者我们为了例子而假装如此)不会立即明显得看出来。为了更好地理解这些函数之间的关系,接下来我们将查看 [自下而上(重)配置文件] 部分,该节提供有关每个函数的主要调用方的信息。检查此部分,我们会发现: +我们看到,前 3 个条目占了程序占用的 CPU 时间的 72.1%。从这个输出中,我们立即看到至少 51.8% 的 CPU 时间被称为 PBKDF2 的函数占用。它与用户密码中的哈希生成相对应。然而,较低的两个条目的因素是如何进入我们的应用程序(或者我们为了例子而假装如此)不会立即明显得看出来。为了更好地理解这些函数之间的关系,接下来我们将查看[自下而上(重)配置文件]部分,该节提供有关每个函数的主要调用方的信息。检查此部分,我们会发现: ``` ticks parent name @@ -159,7 +159,7 @@ node --prof-process isolate-0xnnnnnnnnnnnn-v8.log > processed.txt 分析此节需要的工作量比上面的原始刻度计数多一点。 在上面的每个“调用栈”中,父列中的百分比将告诉您在当前行中函数调用了上面行中的函数所占的样本百分比。例如,在中间“呼叫堆栈”以上为 _sha1_block_data_order,我们看到 `_sha1_block_data_order` 发生在 11.9% 样品,我们知道从上面的原始计数。然而,在这里我们也可以说,它总是由 Node.js 内部的 pbkdf2 函数调用加密模块。我们看到,同样 `_malloc_zone_malloc` 被称为几乎完全相同的 pbkdf2 功能。因此,使用中的信息这种观点,我们可以说,我们从用户的密码帐户计算的哈希不仅为上面所述的 51.8%,但也是前 3 的 CPU 时间采样函数,因为调用 `_sha1_block_data_order` 和`_malloc_zone_malloc` 是代表 pbkdf2 的功能而制作的。 -在这一点上,很明显,,基于密码的哈希生成应该是我们优化的目标。谢天谢地,您已经完全了解了 [异步编程的好处][],并且您认识到从用户密码生成哈希的工作正在以同步方式进行,从而绑定了事件循环。这将阻止我们在计算哈希时处理其它传入请求。 +在这一点上,很明显:基于密码的哈希生成应该是我们优化的目标。谢天谢地,您已经完全了解了[异步编程的好处][],并且您认识到从用户密码生成哈希的工作正在以同步方式进行,从而绑定了事件循环。这将阻止我们在计算哈希时处理其它传入请求。 要解决此问题,请对上述处理程序进行小修改,以使用 pbkdf2 函数的异步版本: diff --git a/locale/zh-cn/docs/guides/timers-in-node.md b/locale/zh-cn/docs/guides/timers-in-node.md index e98773ae05871..8220ea6a00929 100644 --- a/locale/zh-cn/docs/guides/timers-in-node.md +++ b/locale/zh-cn/docs/guides/timers-in-node.md @@ -5,7 +5,7 @@ layout: docs.hbs # Node.js 中的定时器 -Node.js 中的定时器模块包含了隔一定时间执行一遍代码的函数。定时器不必通过 `require()` 的方式引入,因为所有这些方法都是模拟浏览器中 JavaScript 函数,是全局的。为了更好的全面理解何时这些函数将执行,阅读 Node.js 中 [事件轮询](/en/docs/guides/event-loop-timers-and-nexttick/) 是一个好主意。 +Node.js 中的定时器模块包含了隔一定时间执行一遍代码的函数。定时器不必通过 `require()` 的方式引入,因为所有这些方法都是模拟浏览器中 JavaScript 函数,是全局的。为了更好的全面理解何时这些函数将执行,阅读 Node.js 中[事件轮询](/en/docs/guides/event-loop-timers-and-nexttick/)是一个好主意。 ## 用 Node.js 控制时间的连续 @@ -58,7 +58,7 @@ executing immediate: so immediate `setImmediate()` 返回一个 `Immediate` 对象,它可以被用于取消安排的定时任务(见下面的 `clearImmediate()` )。 -注意:不要把 `setImmediate()` 和 `process.nextTick()` 相混淆。它们有一些主要的差别:第一, `process.nextTick()` 将在任何设置好的 `Immediate` 以及任何安排好的 I/O *前* 执行。第二, `process.nextTick()` 是不可擦除的,换句话说,一旦有代码使用 `process.nextTick()` 执行,执行无法中断,这就像一个普通函数一样,具体可以参考 [此教程](/en/docs/guides/event-loop-timers-and-nexttick/#process-nexttick) 来更好地理解 `process.nextTick()` 的操作。 +注意:不要把 `setImmediate()` 和 `process.nextTick()` 相混淆。它们有一些主要的差别:第一, `process.nextTick()` 将在任何设置好的 `Immediate` 以及任何安排好的 I/O *前* 执行。第二, `process.nextTick()` 是不可擦除的,换句话说,一旦有代码使用 `process.nextTick()` 执行,执行无法中断,这就像一个普通函数一样,具体可以参考[此教程](/en/docs/guides/event-loop-timers-and-nexttick/#process-nexttick)来更好地理解 `process.nextTick()` 的操作。 ### "永远的轮询" 执行 ~ *`setInterval()`* diff --git a/locale/zh-cn/docs/guides/working-with-different-filesystems.md b/locale/zh-cn/docs/guides/working-with-different-filesystems.md index 863690d04f0d3..9bc64802976b4 100644 --- a/locale/zh-cn/docs/guides/working-with-different-filesystems.md +++ b/locale/zh-cn/docs/guides/working-with-different-filesystems.md @@ -11,7 +11,7 @@ Node 公开了许多文件系统的特性。但并不是所有的文件系统都 在你开始与文件系统工作前,你需要知道它是如何工作的。不同的文件系统行为表现差异,而且相互之间有或多或少的特性:如大小写敏感、大小写不敏感、大小写保存、编码格式保存、时间戳解析、扩展特性、节点表、Unix 权限、备用数据流等。 -你应该小心翼翼地通过 `process.platform` 推断文件系统类型。举一个例子,不要假设因为您的程序在 Darwin 系统上运行,因此您正在处理一个不区分大小写的文件系统(HFS+),因为用户可能使用一个区分大小写的文件系统(HFSX)。类似地,不要假设因为您的程序在 Linux 上运行,因此您正在处理支持 Unix 权限和 INODE 的文件系统,因为您可能在特定的外部驱动器上,USB或网络驱动器不支持。 +你应该小心翼翼地通过 `process.platform` 推断文件系统类型。举一个例子,不要假设因为您的程序在 Darwin 系统上运行,因此您正在处理一个不区分大小写的文件系统(HFS+),因为用户可能使用一个区分大小写的文件系统(HFSX)。类似地,不要假设因为您的程序在 Linux 上运行,因此您正在处理支持 Unix 权限和 INODE 的文件系统,因为您可能在特定的外部驱动器上,USB 或网络驱动器不支持。 操作系统可能不容易推断文件系统行为,但都不会丢失。不用保存所有已知文件系统和行为的列表(这总是不完整的),您可以探测文件系统来查看它实际上是如何运行的。容易探测的某些特征的存在或不存在常常足以推断更难探测的其它特征的行为。 @@ -19,7 +19,7 @@ Node 公开了许多文件系统的特性。但并不是所有的文件系统都 ## 避免最低公分母方法 -您可能会试图使程序像最低公分母文件系统一样,通过将所有文件名规范为大写,将所有文件名规范为NFC Unicode 格式,并将所有文件时间戳归一化以表示 1 秒分辨率。这将是最低的公分母方法。 +您可能会试图使程序像最低公分母文件系统一样,通过将所有文件名规范为大写,将所有文件名规范为 NFC Unicode 格式,并将所有文件时间戳归一化以表示 1 秒分辨率。这将是最低的公分母方法。 不要这样做。您只能安全地与文件系统进行交互,该文件系统在各个方面具有完全相同的最低公分母特性。您将无法以用户期望的方式使用更高级的文件系统,并且您会遇到文件名或时间戳冲突。您肯定会通过一系列复杂的依赖事件造成用户数据丢失和损坏。你会不断给你自己制造缺陷,而且解决起来很困难。 @@ -29,7 +29,7 @@ Node 公开了许多文件系统的特性。但并不是所有的文件系统都 ## 采用超集方法 -充分利用你支持的每一个平台,采用超集方法。例如,一个可移植的备份程序应该正确地在Windows系统之间同步文件或文件夹,即使在 Linux 系统上不支持 btime,也不应该破坏或更改它。相同的便携式备份程序应在 Linux 之间正确同步 Unix 权限系统且不应破坏或更改 Unix 权限,即便 Unix 权限在 Windows 系统上不被支持。 +充分利用你支持的每一个平台,采用超集方法。例如,一个可移植的备份程序应该正确地在 Windows 系统之间同步文件或文件夹,即使在 Linux 系统上不支持 btime,也不应该破坏或更改它。相同的便携式备份程序应在 Linux 之间正确同步 Unix 权限系统且不应破坏或更改 Unix 权限,即便 Unix 权限在 Windows 系统上不被支持。 通过使程序像更高级的文件系统一样处理不同的文件系统。支持所有可能功能的超集: 区分大小写、保存大小写、Unicode 敏感编码、Unicode 格式保存、Unix 权限、高分辨率纳秒时间戳、扩展属性等。 @@ -41,14 +41,14 @@ Node 公开了许多文件系统的特性。但并不是所有的文件系统都 ## 大小写保留 -您可以创建一个名为 `test/abc` 的目录,并惊讶地看到有时 `fs.readdir('test')` 返回 `['ABC']` 。这不是 Node 的 bug。Node 返回文件名, 因为文件系统存储它;而不是所有文件系统 +您可以创建一个名为 `test/abc` 的目录,并惊讶地看到有时 `fs.readdir('test')` 返回 `['ABC']` 。这不是 Node 的 bug。Node 返回文件名,因为文件系统存储它;而不是所有文件系统 支持大小写保存。某些文件系统将所有文件名转换为大写(或小写)。 ## Unicode 编码格式保存 *大小写保存和 Unicode 编码保存是相似的概念。要了解为什么要保留 Unicode 编码,请确保首先了解为什么应保留大小写。在正确理解时,Unicode 形式保存也同样简单。* -Unicode 可以使用多个不同的字节序列对相同的字符进行编码。多个字符串可能看起来相同,但有不同的字节序列。使用 UTF-8 字符串时请注意,您的期望与 Unicode 的工作方式一致。正如您不希望所有 UTF-8 字符都编码到单个字节一样, 您不应该期望用人的肉眼看上去是是一样的几个 UTF-8 字符串一定具有相同的字节表示形式。这可能只是一个期望,你可以有 ASCII,但不是 UTF-8。 +Unicode 可以使用多个不同的字节序列对相同的字符进行编码。多个字符串可能看起来相同,但有不同的字节序列。使用 UTF-8 字符串时请注意,您的期望与 Unicode 的工作方式一致。正如您不希望所有 UTF-8 字符都编码到单个字节一样,您不应该期望用人的肉眼看上去是是一样的几个 UTF-8 字符串一定具有相同的字节表示形式。这可能只是一个期望,你可以有 ASCII,但不是 UTF-8。 您可以创建一个名为 `test/café` 的目录(带有字节序列的 `<63 61 66 c3 a9>` 和 `string.length === 5` 的 NFC Unicode 编码)。然后你会惊讶地看到,有时 `fs.readdir('test')` 会返回 `['café']`(带有字节序列的 `<63 61 66 65 cc 81>` 和 `string.length === 6` 的 NFD Unicode 编码)。这不是 Node 的缺陷。Node 返回文件名因为文件系统存储它,而不是所有文件系统支持 Unicode 形式保存。 @@ -60,7 +60,7 @@ Unicode 不敏感编码和 Unicode 编码保存是两种不同的文件系统行 ## 比较不同的 Unicode 编码 -节点提供了 `string.normalize('NFC' / 'NFD')`,你可以使用它正常化一个 UTF-8 字符串, 无论是 NFC 或 NFD。您不应将输出从该函数中存储,而只将其用作比较函数的一部分以测试两个 UTF-8 字符串是否与用户看起来相同。 +节点提供了 `string.normalize('NFC' / 'NFD')`,你可以使用它正常化一个 UTF-8 字符串,无论是 NFC 或 NFD。您不应将输出从该函数中存储,而只将其用作比较函数的一部分以测试两个 UTF-8 字符串是否与用户看起来相同。 你可以使用 `string1.normalize('NFC') === string2.normalize('NFC')` 或者 `string1.normalize('NFD') === string2.normalize('NFD')` 作为你的比较函数,至于使用哪种编码格式并不重要。 @@ -78,7 +78,7 @@ Unicode 不敏感编码和 Unicode 编码保存是两种不同的文件系统行 规范化实际上是一个有损的哈希代码。您可以使用它来测试某些类型的等价性(例如,即使它们有不同的字节序列,也可以使用多个字符串看起来相同)。但您永远不能将其用作实际数据的替代。您的程序应根据需要传递文件名和时间戳数据。 -您的程序可以在 NFC(或它喜欢的任何 Unicode 形式组合)中创建新数据,或使用小写或大写的文件名,或者使用 2 秒的分辨率时间戳。但程序不应通过强制大小写 / Unicode 编码 / 时间戳规范化来损坏现有用户数据。相反,在程序中采用超集方法并保留大小写、Unicode 窗体和时间戳解析。这样, 您就能够安全地与执行同样操作的文件系统进行交互。 +您的程序可以在 NFC(或它喜欢的任何 Unicode 形式组合)中创建新数据,或使用小写或大写的文件名,或者使用 2 秒的分辨率时间戳。但程序不应通过强制大小写 / Unicode 编码 / 时间戳规范化来损坏现有用户数据。相反,在程序中采用超集方法并保留大小写、Unicode 窗体和时间戳解析。这样您就能够安全地与执行同样操作的文件系统进行交互。 ## 适当地使用规范化比较函数 @@ -86,6 +86,6 @@ Unicode 不敏感编码和 Unicode 编码保存是两种不同的文件系统行 ## 为比较函数的细微差别做好准备 -请注意,您的比较函数与文件系统的功能匹配(或者,如果可能的话,可以探测文件系统,以查看它如何实际进行比较的)。例如,不区分大小写比简单的 `toLowerCase()` 复杂。事实上 `toUpperCase()` 通常比 `toLowerCase()` 好(因为它处理某些外语字符的方式不同)。但是, 最好还是探测文件系统,因为每个文件系统都有自己的编码比较表。 +请注意,您的比较函数与文件系统的功能匹配(或者,如果可能的话,可以探测文件系统,以查看它如何实际进行比较的)。例如,不区分大小写比简单的 `toLowerCase()` 复杂。事实上 `toUpperCase()` 通常比 `toLowerCase()` 好(因为它处理某些外语字符的方式不同)。但是最好还是探测文件系统,因为每个文件系统都有自己的编码比较表。 例如,苹果的 HFS+ 将文件名规范化为 NFD 形式,但此 NFD 表单实际上是当前 NFD 表单的较旧版本,有时可能与最新的 Unicode 标准的 NFD 形式稍有不同。不要期望 HFS+ NFD 和 Unicode NFD 总是完全相同的。 diff --git a/locale/zh-cn/docs/index.md b/locale/zh-cn/docs/index.md index 7aa032faef6d8..a24d55a60e355 100644 --- a/locale/zh-cn/docs/index.md +++ b/locale/zh-cn/docs/index.md @@ -13,7 +13,7 @@ labels: * ES6 特性 * 指南 -## API函数接口文档 +## API 函数接口文档 [API 函数接口文档](https://nodejs.org/api/) 提供了在 Node.js 中的函数或者对象的详细信息。这个文档告诉你什么方法该用什么参数,方法返回值是什么以及使用那个方法会有什么错误异常。它同时也告知你不同版本中的 Node.js 有哪些方法是可用的。 diff --git a/locale/zh-cn/docs/meta/topics/dependencies.md b/locale/zh-cn/docs/meta/topics/dependencies.md index 6d1bfe06e840e..44f8e020423ee 100644 --- a/locale/zh-cn/docs/meta/topics/dependencies.md +++ b/locale/zh-cn/docs/meta/topics/dependencies.md @@ -23,7 +23,7 @@ Node.js 依赖于以下一些依赖项,这样它才能正常工作。 ### V8 -V8 类库为 Node.js 提供了 JavaScript引擎,Node.js 通过 V8 C++ 的 API 函数接口进行操控, V8 由谷歌公司维护,用于谷歌浏览器中。 +V8 类库为 Node.js 提供了 JavaScript 引擎,Node.js 通过 V8 C++ 的 API 函数接口进行操控, V8 由谷歌公司维护,用于谷歌浏览器中。 * [相关文档](https://v8docs.nodesource.com/) diff --git a/locale/zh-cn/download/package-manager.md b/locale/zh-cn/download/package-manager.md index 80158797f03eb..18632ab1bca9d 100644 --- a/locale/zh-cn/download/package-manager.md +++ b/locale/zh-cn/download/package-manager.md @@ -31,7 +31,7 @@ title: 通过包管理器安装 Node.js 因为 Android 版的 Node.js 目前处于实验阶段,所以当下不提供预编译版本。 -但是你有一些第三方的解决方案可供选择:拿 [Termux](https://termux.com/) 来说,它为安卓提供了终端模拟器和 Linux 环境,以及内置的包管理器和 [可扩展应用集](https://github.com/termux/termux-packages),其中包含了大量预编译的应用。在 Termux 中,以下的命令将会安装最新版 Node.js: +但是你有一些第三方的解决方案可供选择:拿 [Termux](https://termux.com/) 来说,它为安卓提供了终端模拟器和 Linux 环境,以及内置的包管理器和[可扩展应用集](https://github.com/termux/termux-packages),其中包含了大量预编译的应用。在 Termux 中,以下的命令将会安装最新版 Node.js: ```bash pkg install nodejs @@ -91,7 +91,7 @@ Node.js 长期支持版(LTS)各类版本可以通过 IBM 处获得,使用 yum install nodejs12 ``` -Node.js 也可以通过客户端访问解决方案产品(IBM i Access Client Solutions)安装。具体参考 [支持文档](http://www-01.ibm.com/support/docview.wss?uid=nas8N1022619)。 +Node.js 也可以通过客户端访问解决方案产品(IBM i Access Client Solutions)安装。具体参考[支持文档](http://www-01.ibm.com/support/docview.wss?uid=nas8N1022619)。 ## NetBSD @@ -109,7 +109,7 @@ pkgin -y install nodejs ## nvm Node 版本管理器是一个用于管理多个已发布的 Node.js 不同版本的 bash 脚本。它允许你执行诸如“安装”、“卸载”以及“版本切换”等诸多功能。 -使用 [安装脚本](https://github.com/creationix/nvm#install-script) 安装 nvm。 +使用[安装脚本](https://github.com/creationix/nvm#install-script)安装 nvm。 对于 Unix / OS X 系统,Node.js 从源代码构建,并通过 [nvm](https://github.com/creationix/nvm) 安装到你所期望的地方。 @@ -147,7 +147,7 @@ pkg_add node ## openSUSE 和 SLE -在以下安装包中,Node.js在以下主版本库中可用: +在以下安装包中,Node.js 在以下主版本库中可用: * **openSUSE Leap 42.2**: `nodejs4` * **openSUSE Leap 42.3**: `nodejs4`, `nodejs6` diff --git a/locale/zh-cn/get-involved/collab-summit.md b/locale/zh-cn/get-involved/collab-summit.md index c72d18a7a341d..bffc59f24a1ff 100644 --- a/locale/zh-cn/get-involved/collab-summit.md +++ b/locale/zh-cn/get-involved/collab-summit.md @@ -11,4 +11,4 @@ layout: contribute.hbs 欢迎所有人参加。峰会期间,组长们会在新进的协作者融入工作议程之前协助他们加入想要贡献的群组。 这是一个你可以学习社群事务的好机会,同时也能贡献及精进你的技能。在进行现场分组讨论之前,工作组会先安排行程好让人们可以互相熟悉对方。 -期待能与你在协作者峰会中相见![峰会回顾](https://github.com/nodejs/summit) 中有即将到来及过往的协作者峰会信息,并记得看看 [议题](https://github.com/nodejs/summit/issues),里头分享了个别工作组及委员会的讨论。 +期待能与你在协作者峰会中相见![峰会回顾](https://github.com/nodejs/summit) 中有即将到来及过往的协作者峰会信息,并记得看看[议题](https://github.com/nodejs/summit/issues),里头分享了个别工作组及委员会的讨论。 diff --git a/locale/zh-cn/get-involved/contribute.md b/locale/zh-cn/get-involved/contribute.md index b339e43bc778b..9dfe61d821607 100644 --- a/locale/zh-cn/get-involved/contribute.md +++ b/locale/zh-cn/get-involved/contribute.md @@ -44,4 +44,4 @@ layout: contribute.hbs * 参与工作组 * 参与其它 Node.js 社区群 -若你自己认为已经做出重大贡献,却没有被授予提交权限,你可以尝试 [开启 TSC 议题](https://github.com/nodejs/TSC/issues) 或 [直接联系 TSC 成员](https://github.com/nodejs/TSC#current-members) 以获得相应权限。 +若你自己认为已经做出重大贡献,却没有被授予提交权限,你可以尝试[开启 TSC 议题](https://github.com/nodejs/TSC/issues)或[直接联系 TSC 成员](https://github.com/nodejs/TSC#current-members)以获得相应权限。 diff --git a/locale/zh-cn/security.md b/locale/zh-cn/security.md index 2ee1146c93c90..16da6c0ad4133 100644 --- a/locale/zh-cn/security.md +++ b/locale/zh-cn/security.md @@ -27,7 +27,7 @@ Node.js 项目参与了一个为安全研究员和负责任的公众披露者的 你应该向第三方模块相关负责维护人直接汇报此类安全问题,并通过 [Node 生态安全团队](https://hackerone.com/nodejs-ecosystem)进行组织协调。 -有关于此计划的详情部分可以在 [安全工作组](https://github.com/nodejs/security-wg/blob/master/processes/third_party_vuln_process.md) 寻找到。 +有关于此计划的详情部分可以在[安全工作组](https://github.com/nodejs/security-wg/blob/master/processes/third_party_vuln_process.md)寻找到。 感谢你为提升 Node.js 及其生态系统的安全作出贡献。我们非常感激并认可你的努力以及负责任的公开信息。 @@ -43,7 +43,7 @@ Node.js 项目参与了一个为安全研究员和负责任的公众披露者的 * 通常禁运日期将在 CVE 发布之时起,在 72 小时内设置。但是这可能会因安全缺陷的严重程度或应用修复程序的困难程度而有所不同。 -* 这个过程可能需要一些时间,特别是当需要与其他项目的维护人员进行协调时。但是将尽一切努力尽可能及时地处理 缺陷漏洞。但是我们仍必须遵循上面的发布过程,以确保以一致的方式处理泄漏。 +* 这个过程可能需要一些时间,特别是当需要与其他项目的维护人员进行协调时。但是将尽一切努力尽可能及时地处理缺陷漏洞。但是我们仍必须遵循上面的发布过程,以确保以一致的方式处理泄漏。 ## 收到安全更新 @@ -54,5 +54,4 @@ Node.js 项目参与了一个为安全研究员和负责任的公众披露者的 ## 对于此政策的评论与建议 -如果你对于如何提高优化此流程有独特建议,请通过发送一个 [请求](https://github.com/nodejs/nodejs.org) -或是 [创建新提议](https://github.com/nodejs/security-wg/issues/new) 来与我们讨论。 +如果你对于如何提高优化此流程有独特建议,请通过发送一个[请求](https://github.com/nodejs/nodejs.org)或是[创建新提议](https://github.com/nodejs/security-wg/issues/new)来与我们讨论。