电子书举荐

Digital Forensics with Kali Linux, 2nd Edition

Debugging CSS

Practical Entity Framework Core 6: Database Access for Enterprise Applications, 2nd Edition

Hacking: Learn How to Hack Like a Pro

Hands on Hacking

JavaScript Cookbook: Programming the Web, 3rd Edition

Interactive Data Visualization with Python

Introduction to Deep Learning

Lean Python: Learn Just Enough Python to Build Useful Tools

Learn C++ Quickly

从nodejs.org下载安装Node.js安装包

Node.js官网https://nodejs.org/en/网站提供了Windows、macOS、Linux和Solaris等零碎的二进制安装文件。咱们只需进入Node.js官网,点击装置按钮,而后运行安装程序就可装置Node.js。对于带有包治理 的零碎,如咱们下面探讨的,最好应用包管理系统装置。这是因为你会发现应用包管理系统装置形式更加容易更新Node.js的最新版本。然而种装置形式并不适宜所有开发者,起因如下:

  • 有些人更喜爱装置二进制文件,而不是应用包管理器装置软件。
  • 他们抉择的零碎没有包管理系统。
  • 他们的包管理系统中的Node.js实现已过期。

关上Node.js网站,您就会看到如下屏幕截图所示的内容。该页面尽最大致力确定您的操作系统并提 供适当的版本下载。如果您须要其余版本,请单击题目中的下载链接以获取所有可下载的版本:

macOS零碎的Node.js安装包是一个PKG文件。不论是MacOS零碎还是Windows零碎,装置过程都和装置惯例软件过程是一样的。
在装置Node.js程序过程中,命令行工具例如node和npm也会同时被装置。因而装置实现后,你能够间接应用npm和npx命令运行node.js程序。Windows零碎还提供了一个预配置的Windows命令shell版本,能够很好地与Node.js配合应用。
正如您你刚刚理解到的,咱们大多数人都喜爱应用Node.js安装包装置Node.js。然而,有时咱们必须应用源代码装置Node.js。

在相似POSIX的零碎上应用源代码装置

应用Node.js安装包装置Node.js发行版是首选的装置办法。然而应用源代码装置Node.js具备以下几个长处:

  • 你能够依据须要优化编译器设置。
  • 你能够穿插编译,比方编译嵌入式ARM零碎。
  • 你能够依据须要装置多个Node.js版本以进行测试。
  • 你可能正在解决Node.js。

当初您曾经理解为什么要应用源代码装置Node.js,让咱们通过一些构建脚本来入手安 装Node.js。装置过程遵配置、制作和安装程序等惯例装置过程,您可能曾经应用其余开源软件包执行了该过程。如果没有,请不要放心,我将领导你实现整个过程。
官网装置阐明文件见README.md文件,网址为https://github.com/nodejs/nod...。

装置前提条件

在应用源代码装置Node.js前,咱们须要装置三个工具:C编译器、Python和OpenSSL库。Node.js编译过程查看会检测这个三款个工具是否 存在。如果C编译器或Python不存在,则编译将失败。请用以下命令将查看C编译器和Python是否存已装置:

$ cc --versionApple LLVM version 10.0.0 (clang-1000.11.45.5)Target: x86_64-apple-darwin17.7.0Thread model: posixInstalledDir:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xct oolchain/usr/bin $ pythonPython 2.7.16 (default, Oct 16 2019, 00:35:27)[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwinType "help", "copyright", "credits" or "license" for more information. >>>

具体的装置办法取决于您的操作系统。
Node.js构建工具正在更新以反对Python 3.x。Python2.x正处于生命周期完结阶段,打算于2019年底完结保护,因而倡议你将Python2.x更新到Python3.x。
在编译Node.js源代码之前,咱们必须装置正确的工具。在macOS上,有几个非凡的事项须要留神。

在macOS上装置开发者工具

开发工具(如GCC)是macOS上的可选装置工具。侥幸的是,这些很容易取得。
你能够首先装置Xcode,Xcode能够通过Mac利用商店收费下载。只需搜寻Xcode并单击“获取”按钮。安 装Xcode后,关上终端窗口并输出以下内容:

$ xcode-select --install

这就装置了Xcode命令行工具

无关更多信息,请拜访:http://osxdaily.com/2014/02/1...。
当初咱们曾经装置了须要的工具,能够持续编译Node.js源代码。

在所有类POSIX的零碎应用源代码装置Node.js

应用源代码编译装置Node.js的过程如下:

  1. 源代码下载地址http://nodejs.org/download。
  2. 应用./Configure配置用于构建的源代码。
  3. 运行make,而后运行make install

源代码绑定包能够通过浏览器下载,也能够按以下形式下载替换你喜爱的版本:

$ mkdir src$ cd src$ wget https://nodejs.org/download/release/v14.0.0/node-v14.0.0.tar.gz $ tar xvfz node-v14.0.0.tar.gz$ cd node-v14.0.0

当初咱们通过配置源代码来构建Node.js。与许多其余开源包一样,有一系列选项可用于自定义构建Node.js:

$ ./configure --help

要将Node.js装置到你的主目录,请运行以下命令:

$ ./configure --prefix=$HOME/node/14.0.0 ..output from configure

如果要同时装置多个版本的Node.js,请应用以下命令将将版本号配置到PATH中。这样,每个版本将被装置 到一个独自的目录中。而后,通过更改响应的PATH变量就能够很简略地在Node.js的版本之间切换:

#On bash shell:$ export PATH=${HOME}/node/VERSION-NUMBER/bin:${PATH} # On csh$ setenv PATH ${HOME}/node/VERSION-NUMBER/bin:${PATH}

装置多个Node.js版本的一种更简略的办法是应用nvm脚本,这种装置形式咱们将在前面理解。
如果要将Node.js装置到系统目录中,只需省略--prefix,Node.js就会被默认装置到系统目录/usr/ local中。
期待一段时间,装置就会进行,并且可能曾经胜利地配置了源代码树,以便将Node.js装置到你抉择的目录中。如果装置不胜利,则打印的谬误音讯将形容须要修复的内容。一旦满足配置脚本的要求,就能够进入下一 步。
在满足配置脚本的状况下,您能够编译软件:

$ make.. a long log of compiler output is printed $ make install

如果要将Node.js装置到系统目录中,请应用以下代码执行最初一步:

$ echo 'export PATH=$HOME/node/14.0.0/bin:${PATH}' >>~/.bashrc $ . ~/.bashrc

或者,对于csh用户,应用以下语法导出生成的环境变量:

$ echo 'setenv PATH $HOME/node/14.0.0/bin:${PATH}' >>~/.cshrc $ source ~/.cshrc

装置构建时,下面的命令会创立一个目录构造,如下所示:

$ ls ~/node/14.0.0/bin   include   lib   share $ ls ~/node/14.0.0/binnode npm npx

当初,咱们曾经理解了如何在类UNIX零碎上应用源代码装置Node.js,咱们能够在Windows上执行同样的 操作。

在Window上应用源代码装置Node.js

后面援用的BUILDING.md文档蕴含了装置阐明。您能够应用Visual Studio的构建工具或残缺的Visual Studio 2017或2019产品装置Node.js:

  • Visual Studio 2019: https://www.visualstudio.com/...
  • 构建工具: https://visualstudio.microsof...

须要另外三个工具:

  • Windows版Git :http://git-scm.com/download/win
  • Python:https://www.python.org/
  • OpenSSL:https://www.openssl.org/source/ 和https://wiki. openssl.org/index.php/Binaries
  • 用于OpenSSL的Netwide汇编器(NASM):https://www.nasm.us/

而后,运行内置的.\vcbuild脚本执行构建。
咱们曾经学习了如何装置一个Node.js实例,当初让咱们来理解一下如何装置多个实例。

应用nvm装置多个版本Node.js

咱们通常不会装置多个版本的Node.js,因为这样做会减少零碎的复杂性。然而,如果您正在对Node.js进行模仿黑客攻击演练,或者针对不同的Node.js版本测试你的利用,那么你可能须要装置多个Node.js实例。装置办法只是对后面装置办法进行简略的批改。
在后面探讨从源代码构建Node.js时,咱们留神到能够在独自的目录中装置多个Node.js实例。如果您须要 定制的Node.js构建,那么只须要应用源代码装置就能够了。但大多数人都比拟喜爱应用Node.js安装包安 装Node.js并且也能够装置在独自的目录中。
在Node.js版本之间切换只须要将装置Node.js的目录增加到PATH变量中,POSIX零碎应用如下代码:

$ export PATH=/usr/local/node/VERSION-NUMBER/bin:${PATH}

然而工夫一长,保护会变得越来越艰难。因为咱们须要对不同版本的Node.js进行设置,包含npm和咱们 要是用的第三发模块。此外,频繁更改PATH变量也是十分麻烦的,因而有开发者创立了几个版本治理 器,以简化对多个Node.js/npm版本的治理,并提供了更改PATH变量的智能命令:

  • Node 版本管理器:https://github.com/tj/n
  • Node 版本管理器:https://github.com/creationix...

这两个版本管理器都用于保护Node.js的多个版本,并且可能让你非常简单在不同的Node.js版本之间切 换。装置阐明可在这个工具的官方网站上取得。例如,应用nvm,你能够运行以下命令:

$ nvm ls...v6.4.0...v6.11.2v8.9.3v10.15.2...v12.13.1...v14.0.0-> systemdefault -> 12.9.1 (-> v12.9.1)node -> stable (-> v12.13.1) (default) stable -> 12.13 (-> v12.13.1) (default) $ nvm use 10Now using node v10.15.2 (npm v6.4.1)$ node --versionv10.15.2$ nvm use 4.9Now using node v4.9.1 (npm v2.15.11)$ node --versionv4.9.1$ nvm install 14Downloading and installing node v14.0.0... Downloading https://nodejs.org/dist/v14.0.0/node-v14.0.0-darwin-x64.tar.xz... ############... 100.0%Computing checksum with shasum -a 256Checksums matched!Now using node v14.0.0 (npm v6.14.4)$ node --versionv14.0.0$ which node/Users/david/.nvm/versions/node/v14.0.0/bin/node$ /usr/local/bin/node --versionv13.13.0$ /opt/local/bin/node --versionv13.13.0

在本例中,咱们首先列出了已装置的版本。而后,咱们演示了如何切换,并测验切换后的版本。咱们还装置了nvm的新版本。最初,咱们展现了nvm装置Node.js软件包的目录,以及应用MacPorts或Homebrew装置的Node.js版本。
这表明您能够在系统目录中装置Node.js,由nvm治理多个公有的Node.js版本,并依据须要在它们之间切换。新的Node.js版本公布后,即便您的操作系统的官网软件包管理器尚未更新其软件包,也能够应用nvm轻松装置。

在Windows上装置nvm

可怜的是,nvm不反对Windows。侥幸的是,有几个Windows零碎的nvm克隆版本:

  • 实用于Windows的Node.js版本治理实用程序:https://github.com/coreybutle...
  • 实用于Windows的Natural Node.js和npm版本管理器:https://github.com/marcelkleh...

另一种办法是应用WSL。因为在WSL中,Windows 10自带了Linux子系统,所以能够应用nvm自身。然而,让咱们持续关注如何在Windows中装置nvm。
本书中的许多示例都应用nvm-windows应用程序进行了测试。尽管有轻微的执行差别,但其执行与Linux和macOS上的nvm基本相同。最大的变动是nvm use和nvm install命令中的版本号说明符。
应用nvm for Linux和macOS,您能够输出一个简略的版本号,例如nvm use 8,它将主动替换命 名Node.js的最新版本。对于nvm-Windows,nuv use 8与nvm use 8.0.0的作用是雷同的。换句话说,对 于nvm-windows,您必须应用确切的版本号。侥幸的是,应用nvm list available命令能够轻松取得受反对版本的列表。
应用诸如nvm之类的工具简化了针对多个Node.js版本测试Node.js应用程序的过程。
当初咱们能够装置Node.js了,咱们须要确保咱们正在装置任何咱们想要应用的Node.js模块。这须要在咱们的计算机上安装构建工具。

装置原生代码模块的要求

尽管在本书中咱们不会探讨原生代码模块开发,但咱们的确须要确保它们能够构建。NPM存储库中的一 些模块是原生代码,它们必须用C或C++编译器编译,以构建相应的.No.Frm文件(.No.Exchange用于二 进制原生代码模块)。
该模块通常是其余库的包装器。例如,libxslt和libxmljs模块是同名C/C++库的包装器。该模块蕴含C/C++源代码,装置后会主动运行应用node-gyp编译的脚本。
node-gyp工具是一个用node.js编写的跨平台命令行工具,用于编译node.js的原生附加模块。咱们屡次 提到的原生代码模块就是用这个工具编译的,用于与Node.js一起应用。
通过运行以下命令,您能够很容易地看到这一点:

$ mkdir temp$ cd temp$ npm install libxmljs libxslt

这是在长期目录中实现的,因而您能够在当前删除它。如果您的零碎没有装置编译原生代码模块的工 具,您将看到谬误音讯。否则,您将在输入中看到一个node-gyp执行,前面是许多显然与编译C/C++文 件相干的文本行。
node-gyp工具的先决条件与从源代码编译node.js的先决条件相似,即C/C++编译器、Python环境和其余构建工具,如Git。对于Unix、macOS和Linux零碎,这些都很容易取得。对于Windows,您应该装置以下组件:

  • Visual Studio 构建工具: https://www.visualstudio.com/...
  • Windows版Git: http://git-scm.com/download/win
  • Windows版Python: https://www.python.org/

通常,您不须要装置node-gyp,这是因为它作为npm的一部分主动装置的。这样,npm就能够主动构建原生代码模块。
其GitHub存储库蕴含文档,请拜访:https://github.com/nodejs/nod...。
浏览其存储库中的node-gyp文档将使您更分明地理解后面探讨的编译先决条件以及开发原生代码模块。 这是一个非显式依赖关系的示例。最好明确申明软件包所依赖的所有内容。在Node.js中,依赖项在package.json中申明,以便包管理器(npm或Thread)能够下载和设置所有内容。但这些编译器工具 是由操作系统包管理系统设置的,不受npm或yarn的管制。因而,咱们不能显式地申明这些依赖项。
咱们刚刚理解到Node.js不仅反对JavaScript编写的模块,还反对其余编程语言编写的模块。咱们还学习了如何装置此类模块。接下来,咱们将理解Node.js的版本号。

抉择要应用的Node.js版本和版本策略

在上一节中,咱们只是看到了太多不同的Node.js版本号,您可能会对应用哪个版本感到困惑。本书应用的Node.js版本为14.x,咱们将介绍的所有内容都与Node.js 10.x和任何后续版本兼容。
从Node.js 4.x开始,Node.js团队采纳了双轨办法。偶数版本(4.x、6.x、8.x等等)是他们所谓的长期支 持(LTS),而奇数版本(5.x、7.x、9.x等等)是以后新个性开发版本。尽管开发分支保持稳定, 但LTS版本定位为供生产应用,并将在几年内失去更新。
在撰写本文时,Node.js 12.x是以后的LTS版本;Node.js 14.x曾经公布,最终将更新为LTS版本。
除了通常的性能改良和bug修复之外,各个新的Node.js版本的一个次要影响是引入了最新的V8 JavaScript引擎版本。反过来,这意味着在V8团队在保护V8引擎时会一直引入更多的ES2015/2016/2017功 能。Node.js 8.x新增了async/await函数,Node.js 10.x反对规范的ES6模块格局,Node.js 14.x将齐全支 持ES6模块格局。
咱们要思考新的Node.js版本是否会毁坏您的代码。随着V8一直被退出ECMAScript新个性,并 且Node.js团队有时会对Node.js API进行破坏性的更改,新的语言个性总是被增加。如果您的代码曾经在 某个Node.js版本上进行了测试,那么它是否能够在晚期版本上运行?Node.js的更改会突破咱们的一些假 设吗?
npm的作用确保咱们的包在正确的Node.js版本上执行。这意味着咱们能够在package.json文件中为包指定兼容的Node.js版本(咱们将在第3章摸索Node.js模块中进行探讨)。
咱们能够向package.json增加一个版本条件,如下所示:

engines: {      "node": ">=8.x" }

该代码要求给定的包与Node.js 8.x或更高版本兼容。
当然,您的开发环境能够装置多个Node.js版本。您须要申明软件反对的版本,以及您心愿评估的任何更 高版本。
咱们刚刚理解了Node.js社区如何治理发行版和版本号。咱们的下一步是探讨要应用的编辑器。

为Node.js抉择编辑器和调试器

因为Node.js代码是JavaScript,因而所有反对JavaScript的编辑器都能够抉择。不像其余一些语言那么复 杂,以至于带代码补全性能是IDE必须具备的,一个简略的编程编辑器齐全能够满足Node.js开发的需 求。
有两个编辑器值得一提,因为它们自身就是用Node.js编写的:Atom和Microsoft Visual Studio Code。 Atom(https://atom.io/)) 将本人形容为21世纪的可高度自定义的编辑器。它能够通过应用Atom API编 写Node.js模块进行扩大,并且配置文件很容易编辑。换句话说,它能够通过与许多其余编辑器一样的方 式进行目定斗,也就是说,您能够编写一个软件模块来减少编辑器的性能。Electron框架是为了构 建Atom而创造的,它是应用Node.js构建桌面应用程序的一种非常简单的办法。
Microsoft Visual Studio Code(https://code.visualstudio.com/) 也是一个可高度自定义编辑器,并且也 是开源的,并应用Electron开发的。然而,它不是一个空洞的“我也是”编辑器,在走Atom的路同时 不,Visual Studio代码自身就是一个牢靠的程序员编辑器,并且也有很多乏味的性能。
对于调试器,有几个乏味的抉择。从Node.js 6.3开始,inspector协定使应用Google Chrome调试器成为 可能。Visual Studio Code有一个内置调试器,也应用inspector协定。
无关调试选项和工具的残缺列表,请参阅 https://nodejs. org/en/docs/guides/debugging-getting-started/。
与编辑器相干的另一项工作是增加扩大以进步编程体验。大多数面向程序员的编辑器容许您扩大性能并 帮助编写代码。一个简略的例子是JavaScript、CSS、HTML等的语法着色性能。代码补全扩大是编辑器帮 助您编写代码性能。一些扩大扫描用于常见谬误的语法错误代码;这些扩大通常应用lint这个词示意。一 些扩大有助于运行单元测试框架。因为的抉择的编辑器切实太多,咱们不能提供具体的倡议。
对于一些人来说,编程编辑器的抉择是一个庄重的问题,因而咱们审慎地建议您应用您喜爱的编辑器, 只有它有助于您编写JavaScript代码即可。接下来,咱们将学习Node.js命令和一些对于运行Node.js脚本 的常识。

运行和测试命令

当初您曾经装置了Node.js,咱们想做两件事来验证装置是否胜利,并相熟Node.js命令行工具和使 用Node.js运行简略脚本。咱们还将再次探讨异步函数,并看一个简略的HTTP服务器示例。咱们将使 用npm和npx命令行工具耒完结本章。

应用Node.js的命令行工具

Node.js有两个根底装置命令:node和npm。咱们曾经看到正在运行node,次要用于运行命令行脚本或 服务器过程。另一个是npm,它是Node.js的包管理器。
验证Node.js是否装置的最简略的无效办法是获取Node.js帮忙。输出以下命令:

$ node --helpUsage: node [options] [ -e script | script.js | - ] [arguments]node inspect script.js [arguments]Options:-v, --version print Node.js version-  e, --eval script evaluate script-  p, --print evaluate script and print result-  c, --check syntax check script without executing-  i, --interactive always enter the REPL even if stdindoes not appear to be a terminal-  r, --require module to preload (option can be repeated)-  script read from stdin (default; interactive mode if a tty)... many more optionsEnvironment variables:NODE_DEBUG ','-separated list of core modules that should print debug information NODE_DEBUG_NATIVE ','-separated list of C++ core debug categories that should print debug outputNODE_DISABLE_COLORS set to 1 to disable colors in the REPLNODE_EXTRA_CA_CERTS path to additional CA certificates fileNODE_NO_WARNINGS set to 1 to silence process warningsNODE_OPTIONS set CLI options in the environment via a space-separated listNODE_PATH ':'-separated list of directories prefixed to the module search path... many more environment variables

咱们失去了很多的输入内容,这内容不需具体理解。关键在于node--help提供了很多有用的信息。
请留神,Node.js和V8都有选项(在后面的命令行中未显示)。记住Node.js是构建在V8之上的;它有本人的选项体系,次要是对于字节码编译或垃圾收集和堆算法的细节。输出node --v8-options就能够查看 这些选项的残缺列表。
咱们能够在命令行上指定选项、单个脚本文件以及该脚本的参数列表。咱们将在下一节中进一步探讨脚 本参数并应用Node.js运行一个简略的脚本。
运行没有参数的Node.js能够让咱们应用JavaScript shell间接编写运行JavaScript代码:

$ node> console.log('Hello, world!'); Hello, world! undefined

咱们在Node.js脚本中编写的所有代码都能够在这里编写。命令解释器提供了良好的面向终端的用户体 验,对于以交互方式解决代码十分有用。

应用Node.js运行简略脚本

当初,让咱们看看如何应用Node.js运行脚本。这很简略;让咱们从后面显示的帮忙信息开始。命令行模式只是一个脚本文件名和一些脚本参数,任何应用其余语言编写脚本的人都应该相熟这些参数。
我你能够应用任意解决的文本编辑器来创立和编辑Node.js脚步,
如VI/VIM、Emacs、Notepad++、Atom、Visual StudioCode、Jedit、BB Edit、TextMate或Komodo等等。如果是一个面向程序员的编辑器,即便只是语法着色,也是很有帮忙的。
对于本书中的源代码文件,放在哪里并不重要。然而,为了整洁起见,您能够在计算机的主目录中创立 一个名为node-web-dev的目录,并在该目录中给每个章节创立一个目录(例如,chap02和chap03)。 首先,创立一个名为ls.js的文件,其中蕴含以下内容:

const fs = require('fs').promises;async function listFiles() {   try {     const files = await fs.readdir('.');      for (const file of files) {        console.log(file);      }     } catch (err) {         console.error(err);     }   }   listFiles();

接下来,在命令框中输出以下命令来运行文件。(译者注:如果js文件不在以后命令框所在目录的话,你须要先 将命令框定位到相应目录下)

$ node ls.js ls.js

这是对unix ls命令的一个非常简单的模拟(如同你不能从名称中看出!)。readdir函数与用于列出目录 中文件的Unix readdir零碎调用命令十分类似。在Unix/Linux零碎上,咱们能够运行以下命令以理解更多 信息:

$ man 3 readdir

当然,man命令能够让你浏览手册页面和第3部介绍的C库。
在函数体内,咱们读取目录并打印其内容。应用require.('fs').promises为咱们提供了返回承诺的fs模块 (文件系统函数)的版本;因而,fs模块在异步函数中运行良好。同样,ES2015 for..of循环结构容许咱们 以一种在异步函数中运行良好的形式循环数组中的元素。
默认状况下,fs模块函数应用最后为Node.js创立的回调范例。因而,大多数Node.js模块都应用回调范例。在异 步函数中,如果函数返回承诺,则更不便,这样就能够应用await关键字。util模块提供了一个函 数util.promisify,它为新式的面向回调的函数生成一个包装函数,因而它返回一个承诺。
这个脚本被硬编码列出当前目录中的文件。真正的ls命令须要一个目录名,因而让咱们略微批改一下该脚 本。
命令行参数位于名为process.argv的全局数组中。因而,咱们能够批改ls.js,将其复制为ls2.js(如下所 示),以查看此数组的工作形式:

const fs = require('fs').promises;async function listFiles() {   try {     var dir = '.';     if (process.argv[2]) dir = process.argv[2];      const files = await fs.readdir(dir);      for (let fn of files) {         console.log(fn);       }        } catch (err) {          console.error(err);    }  }  listFiles();

你能够按如下形式运行:

$ pwd /Users/David/chap02$ node ls2 ..chap01chap02$ node ls2app.jsls.jsls2.js

咱们只是查看命令行参数是否存在,if(process.argv[2])。如果存在,则重写dir变 量,dir=process.argv[2]的值,而后将其用作readdir参数:

$ node ls2.js /nonexistent{ Error: ENOENT: no such file or directory, scandir '/nonexistent' errno: -2,code: 'ENOENT',syscall: 'scandir',path: '/nonexistent' }

如果给定的目录门路不存在,将抛出一个谬误,并应用catch语句打印。
# 编写内联异步箭头函数
有一种不同的形式来写这些例子,有些人感觉更简洁。这些示例是用惯例函数编写的,带有function要害 字申明,但后面有async关键字。ES2015新增了一个个性,即箭头函数,让咱们略微简化了代码。
联合async关键字,async 箭头函数如下所示:

async () => {  // function body}

你能够在任何中央应用箭头函数。例如,该函数能够指定给变量,也能够作为回调传递给另一个函数。 当与async关键字一起应用时,箭头函数体具备异步函数的所有行为。
对于这些示例,能够应用异步箭头函数以立刻执行:

(async () => {  // function body })()

最初一个括号将使内联函数立刻被调用。
而后,因为异步函数返回一个承诺,所以有必要增加一个.catch块来捕捉谬误。综上所述,更改后的示例
如下所示:

const fs = require('fs');(async () => {  var dir = '.';  if (process.argv[2]) dir = process.argv[2];   const files = await fs.readdir(dir);  for (let fn of files) {    console.log(fn);  }})().catch(err => { console.error(err); });

更改前后的代码哪一种更可取,取决于集体爱好。然而,您会发现这两种函数编写形式都在应用,因而 有必要理解把握。
在脚本的顶部调用异步函数时,有必要捕捉并报告所有谬误。未能捕捉和报告谬误可能导致难以确定的 神秘问题。对于本例的原始版本,谬误是通过try/catch块显式捕捉的。在这个版本中,咱们应用.catch块 捕捉谬误。
在异步函数之前,咱们应用了Promise对象,在此之前,咱们应用回调范式。Node.js中依然应用这三种 范式,这意味着您须要理解每一种范式。

转换为异步函数和Promise

在上一节中,咱们探讨了util.promisify及其如向将面向回调的函数转换为返回承诺的函数。后者能够很好 地解决异步函数,因而,函数最好返回一个承诺。
更精确地说,util.promisify将被赋予一个应用谬误优先回调范式的函数。此类函数的最初一个参数是回调 函数,它的第一个参数被解释为谬误批示符,因而称为error-first-callback(谬误优先回 调)。util.promisify返回的是另一个返回承诺的函数。
承诺的作用与谬误优先回调雷同。如果显示谬误,承诺将解析为回绝状态,而如果显示胜利,承诺将解 析为胜利状态。正如咱们在这些示例中看到的,在异步函数中能够很好地解决承诺。
Node.js生态系统有大量应用谬误优先回调的函数。社区曾经开始了一个转换过程,其中函数将返回一个 承诺,并且可能还将首先进行谬误回调,以实现API兼容性。
Node.js 10中的一个新个性就是这种转换的一个例子。fs模块中有一个子模块,名为fs.promises,具备相 同的API,但生成Promise对象。咱们应用该API编写了后面的示例。
另一个抉择是第三方模块fs-extra。此模块具备规范fs模块之外的扩大API。一方面,如果没有提供回调函 数或调用回调函数,该模块的函数将返回一个承诺。此外,该模块还包合几个有用的函数。
在本书前面章节中,咱们将常常应用fs-extra,因为咱们要应用到模块的其余额时函数。无关该模块的文档,请 访https://www.npmjs.com/package...。
util模块有另一个util.callbackify函数,该函数顾名思义将返回承诺的函数转换为应用回调函数的函数。
当初咱们曾经理解了如何运行一个简略的脚本,让咱们看看一个简略的HTTP服务器。

应用Node.js启动服务器

您要运行的许多脚本都是服务器过程;咱们前面会运行很多这样的脚本。为了让你可能熟练地装置验证 和应用Node.js,因而咱们想要运行一个简略的HTTP服务器。让咱们借用Node.js主页上的简略的服务器 脚本(http://nodejs.org)。
创立一个名为app.js的文件,其中蕴含以下内容:

const http = require('http');http.createServer(function (req, res) { res.writeHead(200,   {'Content-Type': 'text/plain'}); res.end('Hello, World!\n');}).listen(8124, '127.0.0.1');console.log('Server running at http://127.0.0.1:8124');

按如下形式运行:

$ node app.jsServer running at http://127.0.0.1:8124

这是能够应用Node.js构建的最简略的web服务器。如果您对它的工作原理感兴趣,请间接浏览 第4章“HTTP服务器和客户端”、第5章“您的第一个Express应用程序”以及第6章“实现挪动优先范式”。然而 当初,只是在中输出http://127.0.0.1:8124 查看Hello,World!信息:

一个须要思考的问题是,当ls.js退出时,为什么这个脚本没有退出。在这两种状况下,脚本的执行都会达到文件的开端;Node.js过程不会在app.js中退出,而会在ls.js中退出。
起因是存在流动事件侦听器。Node.js总是启动一个事件循环,在app.js中,listen函数创立一个实 现HTTP协定的事件(listener)。此侦听器事件将放弃app.js运行,直到您执行某些操作,例如在终端窗 口中按Ctrl+C。在ls.js中,不会创立长时间运行的侦听器事件,因而当ls.js达到其脚本开端时,Node过程将退出。
要应用Node.js执行更简单的工作,咱们必须应用第三方模块。这时候就该npm存储库出场了。

应用npm,Node.js包管理器

Node.js是一个JavaScript解释器,有几个乏味的异步I/O库,它自身就是一个十分根底的零碎。Node.js的 乏味之处之一是Node.js的第三方模块生态系统的快速增长。
该生态系统的外围是npm模块存储库。尽管Node.js模块能够作为源代码下载并手动组装以便用 于Node.js程序,但这样做很繁琐,而且很难实现可反复的构建过程。npm给了咱们一个更简略的办法;npm是Node.js的规范包管理器,它大大简化了下载和应用这些模块的难度。咱们将在下一章具体探讨npm。
你们中眼光敏锐的人会留神到,我你曾经应用后面探讨的所有装置办法装置了nmp。过来,npm是独自 装置的,但当初它与Node.js是捆绑在一起的。
当初咱们曾经装置了npm,让咱们来疾速理解一下。hexy程序是一个用于打印十六进制文件转储的实用 程序。这是一款七十年代的程序,但它依然十分有用。它给咱们提供了疾速装置和试用的性能:

$ npm install -g hexy/opt/local/bin/hexy -> /opt/local/lib/node_modules/hexy/bin/hexy_cmd.js+ hexy@0.2.10 added 1 package in 1.107s

增加-g标记使模块全局可用,而与命令shell的当前工作目录无关。当模块提供命令行界面时,全局装置最有用。当程序包提供命令行脚本时,npm会设置该脚本。我已正确地全局装置hex ,供计算机的所有 用户应用。
依据Node.js的装置形式,它可能须要与sudo一起运行:

1 $ sudo npm install -g hexy

装置后,您能够通过以下形式运行新装置的程序:

$ hexy --width 12 ls.js00000000: 636f 6e73 7420 6673 203d 2072 const.fs.=.r 0000000c: 6571 7569 7265 2827 6673 2729 equire('fs') 00000018: 3b0a 636f 6e73 7420 7574 696c ;.const.util 00000024: 203d 2072 6571 7569 7265 2827 .=.require(' 00000030: 7574 696c 2729 3b0a 636f 6e73 util');.cons 0000003c: 7420 6673 5f72 6561 6464 6972 t.fs_readdir 00000048: 203d 2075 7469 6c2e 7072 6f6d .=.util.prom 00000054: 6973 6966 7928 6673 2e72 6561 isify(fs.rea 00000060: 6464 6972 293b 0a0a 2861 7379 ddir);..(asy 0000006c: 6e63 2028 2920 3d3e 207b 0a20 nc.().=>.{.. 00000078: 2063 6f6e 7374 2066 696c 6573 .const.files 00000084: 203d 2061 7761 6974 2066 735f .=.await.fs_ 00000090: 7265 6164 6469 7228 272e 2729 readdir('.') 0000009c: 3b0a 2020 666f 7220 2866 6e20 ;...for.(fn. 000000a8: 6f66 2066 696c 6573 2920 7b0a of.files).{. 000000b4: 2020 2020 636f 6e73 6f6c 652e ....console. 000000c0: 6c6f 6728 666e 293b 0a20 207d log(fn);...} 000000cc: 0a7d 2928 292e 6361 7463 6828 .})().catch(000000d8: 6572 7220 3d3e 207b 2063 6f6e err.=>.{.con 000000e4: 736f 6c65 2e65 7272 6f72 2865 sole.error(e 000000f0: 7272 293b 207d 293b rr);.});

hexy命令作为全局命令装置,使其易于运行。
在下一章中,咱们将再次深入探讨npm。hexy实用程序既是一个Node.js库,也是一个用于打印这些老式 十六进制转储的脚本。
在开源世界中,满足不同开发者的需要是开源我的项目创立的不一刀衷。启动Thread我的项目的人员发rnnpm没有解决 的开发者的需要,因而创立了一个代替包管理器(Package Manager)的工具,即yarn。他们声 称yarn与npm相比有许多劣势,次要是在性能方面。要理解无关yarn的更多信息,请转到 https://yarnpkg.com/。
对于本书中应用npm的每个示例,都有一个应用纱线的近似等效命令。
对于打包的npm命令行工具,有另一种更简略的办法来应用该工具。

应用npx执行Node.js打包的二进制文件

npm存储库中的一些包是命令行工具,比方咱们后面看到的hexy程序。这些命令行工具在应用之前必须 先装置,这比拟麻烦。在装置node.js时,仔细的你肯定留神到了npx与node和npm命令是一起装置 的。npx旨在通过打消首先要装置命令行软件包的须要,简化从npm存储库运行命令行工具的过程。
上一个示例能够这样运行:

$ npx hexy --width 12 ls.js

在这背地,npx应用npm将包下载到缓存目录,除非包曾经装置到以后我的项目目录中。因为该包位于缓存目 录中,因而只需下载一次。
该工具有许多乏味的选项;要理解更多信息,请转到www.npmjs.com/package/npx。
在本节中,咱们学习了很多Node.js自带的命令行工具,并运行了一个简略的脚本和HTTP服务器。接下 来,咱们将理解JavaScript语言的提高如何影响Node.js平台。

应用ECMAScript 2015、2016、2017及当前的版本晋升Node.js

2015年,ECMAScript委员会公布了期待已久的JavaScript语言的重大更新。更新为JavaScript带来了许多新个性,如承诺、箭头函数和类对象。语言更新为改良奠定了根底,因为它将极大地提高咱们编写干 净、可了解的JavaScript代码的能力。
浏览器制造商正在增加这些急需的性能,这意味着V8引擎也在增加这些性能。从4.x版开始,这些个性就 退出进了Node.js。
要理解Node.js中ES2015/2016/2017/等的以后状态,请拜访https://nodejs.org/en/docs/es6/。
默认状况下,Node.js仅启用V8认为稳固的ES2015、2016和2017性能。能够应用命令行选项启用其余功 能。简直残缺的个性是通过--es_staging选项启用的。网站文档提供了更多信息。
node green网站(http://node.green/) 有一个表,列出Node.js版本中一长串性能的状态。
ES2019语言标准公布在https://www.ecma-internationa...。 TC-39委员会在GitHub上发展工作,网址是:https://github. com/tc39。
ES2015(及更高版本)性能对JavaScript语言进行了重大改良。承诺(Promise)类的一个个性是对Node.js编程中常见习惯用法的根本性反思。在ES2017中,一对新关键字async和await简化了 在Node.js中编写异步代码的过程,这将激励Node.js社区进一步反思平台的常见的习惯用法。
新的JavaScript减少了很个性,但让咱们疾速浏览一下咱们将宽泛应用的这两个个性。
第一种是较轻的函数语法,称为简头函数:

fs.readFile('file.txt', 'utf8', (err, data) => {   if (err) ...; // do something with the error   else ...;  // do something with the data});

这不仅仅是用箭头代替function关键字的语法糖劣势。箭头函数更简洁,也更容易浏览。简洁的代价是改 变箭头函数中this的值。在一般函数中,this在函数内具备一个惟一的值。在箭头函数中,this的值与箭头 函数的作用域雷同。这意味着,当应用箭头函数时,咱们不用将this引入回调函数中,因为this在两个函
数中是一样的。
下一个个性是Promise(承诺)类,用于提早和异步计算。提早代码执行以实现异步行为是Node.js的一 个要害范例,它须要两个习用约定:

  • 异步函数的最初一个参数是回调函数,在执行异步执行时调用回调函数。
  • 回调函数的第一个参数是谬误指示器。

这些约定尽管不便,但却导致了难以了解和保护的多层代码金字塔:

  doThis(arg1, arg2, (err, result1, result2) => {       if (err)...;      else {        // do some work        doThat(arg2, arg3, (err2, results) => {           if (err2)...;          else {             doSomethingElse(arg5, err => {               if (err)..;              else..;            });          }        });      }    });

你不须要了解代码;这只是咱们应用回调时理论产生的状况的概要。依据特定工作须要的步骤,代码金 字塔可能会变得越来越深。承诺将让咱们解决代码金字塔问,进步代码的可靠性,因为错误处理更直 接,更容易捕捉所有谬误。
Promise类的创立如下所示:

    function doThis(arg1, arg2) {      return new Promise((resolve, reject) => {         // execute some asynchronous code        if (errorIsDetected) return reject(errorObject);         // When the process is finished call this:         resolve(result1, result2);      });    }

调用方接管承诺对象,而不是传入回调函数。当正确应用时,后面的金字塔代码能够按如下形式重构:

doThis(arg1, arg2)        .then((result) => {          // This can receive only one value, hence to           // receive multiple values requires an object or array           return doThat(arg2, arg3);        })        .then((results) => {          return doSomethingElse(arg5);        })        .then(() => {          // do a final something        })        .catch((err) => {          // errors land here        });

这是因为如果then函数返回Promise对象,那么Promⅰse类反对链式。
async/await个性实现promise类的承诺,以简化异步编码。此性能在异步函数中变为沉闷状态:

async function mumble() { // async magic happens here}

异步箭头函数如下所示:

const mumble = async () => {  // async magic happens here};

为了理解异步函数范例给咱们带来了多大的改良,让咱们从新编写后面的示例,如下所示:

async function doSomething(arg1, arg2, arg3, arg4, arg5) {  const { result1, result2 } = await doThis(arg1, arg2);  const results = await doThat(arg2, arg3); await doSomethingElse(arg5); // do a final something return finalResult;}

同样,咱们不须要了解代码,只须要看看它的构造。与咱们开始应用的嵌套构造相比,是不是感觉难受爽多了?
wait关键字与Promise一起应用。它会主动期待承诺的解析。如果承诺解析胜利,则返回值,如果承诺解 析为谬误,则抛出该谬误。处理结果和抛出谬误都以通常的形式解决。
此示例还显示了ES2015的另一个性能:解构。能够应用以下代码提取对象的字段:

const { value1, value2 } = { value1: "Value 1", value2: "Value 2", value3: "Value3"};

这例子演示了一个对象有三个字段,但只提取其中两个字段。
为了持续摸索JavaScript的提高,让咱们来看看Babel。