做者 • Dhanjiv Pandey • 本文出处 • 已得到中译受权
• 做者twitter
• 译者主页javascript
译者按: 2018年的文章,其中部分问题放在今天仍然不算过期。
一开始,你能够在了解回调后表扬它。回调地狱是大量嵌套的回调,这使得代码难以阅读和维护。html
让咱们看看下面的代码示例:java
downloadPhoto('http://coolcats.com/cat.gif', displayPhoto) function displayPhoto (error, photo) { if (error) console.error('Download error!', error) else console.log('Download finished', photo) } console.log('Download started')
在这种状况下,Node.js首先声明 displayPhoto
函数。此后,它将调用 downloadPhoto
函数并传递 displayPhoto
函数做为其回调。最后,该代码在控制台上显示Download started
。仅在 downloadPhoto
完成其全部任务的执行后,才会执行 displayPhoto
。node
Node.js在内部使用单线程事件循环来处理排队的事件。可是,若是任务的运行时间比预期的长,则此方法可能致使阻塞整个过程。web
Node.js经过合并回调(也称为higher-order
函数)解决了此问题。所以,只要长时间运行的进程完成执行,就会触发关联的回调。经过这种方法,它能够容许代码在长时间运行的任务以后继续执行。express
然而,上述解决方案看起来很是有前途。可是有时候,这可能会致使复杂且没法读取的代码。更多的状况下它会致使返回的回调链将更长。npm
因为这种史无前例的复杂性,调试代码很是困难,可能会耗费大量时间。有四种解决方案能够解决回调地狱问题。segmentfault
1. 程序模块化.
它建议将逻辑分为较小的模块。而后从主模块将它们链接在一块儿以达到所需的结果。promise
2. 使用 async 机制.
它是一个普遍使用的Node.js模块,提供了一个连续的执行流。
异步模块具备 async.waterfall
API,该API使用下一个回调将数据从一个操做传递到另外一操做。浏览器
另外一个异步API async.map
容许并行遍历项目列表,并使用另外一个结果列表进行回调。
使用异步方法,调用者的回调仅被调用一次。这里的调用者是使用async模块的主方法。
3. 使用 promises 机制.
Promises 提供了另外一种编写异步代码的方法. 它们要么返回执行结果,要么返回 error/exception
.实现promise须要使用 then()
函数,该函数等待 promise
对象返回。它带有两个可选参数,是两个函数。根据promise的状态,只有一个会被调用。若是promise获得实现,则将执行第一个函数调用。可是,若是Promise被拒绝,则将调用第二个函数。
4. 使用 generators.
Generators是轻量级的routines,它们经过yield关键字使函数等待并恢复。生成器函数使用特殊语法function* ()
。他们还可使用诸如promises或thunks
之类的结构来暂停和恢复异步操做,并将同步代码转换为异步代码。
是的,咱们能够在Node.js中建立HTTP Server。咱们可使用http-server
命令来执行此操做。
如下是示例代码:
var http = require('http'); var requestListener = function (request, response) { response.writeHead(200, {'Content-Type': 'text/plain'}); response.end('Welcome Viewers\n'); } var server = http.createServer(requestListener); server.listen(8080); // The port where you want to start with.
Node.js,AJAX和jQuery之间的一个共同特征是它们都是JavaScript的高级实现。可是,它们的用途彻底不一样。
Node.js –
它是用于开发客户端服务器应用程序的服务器端平台。例如,若是咱们必须构建一个在线员工管理系统,那么咱们就不会使用客户端JS来实现它。可是Node.js固然能够作到这一点,由于它运行在相似于Apache的服务器上,而不是运行在浏览器上。
AJAX (aka Asynchronous Javascript and XML) –
它是一种客户端脚本技术,主要用于呈现页面内容而不刷新页面。
jQuery –
它是著名的JavaScript模块,对AJAX、DOM遍历、循环等进行了补充。这个库提供了许多有用的函数来帮助JavaScript开发。不过,使用它不是强制性的,它还管理跨浏览器的兼容性,因此能够帮助您生成高度可维护的web应用程序。
Node.js中有三个关键字构成Globals。它们是 Global
,Process
和Buffer
。
Global
Global关键字表示全局名称空间对象。它充当全部其余global
对象的容器。若是咱们输入console.log(global)
,它会所有打印出来。
关于全局对象要注意的重要一点是,并不是全部对象都在全局范围内,其中一些属于模块范围。所以,不使用var关键字声明它们或将它们添加到Global对象是明智的。
使用var关键字声明的变量在模块中变为局部变量,而那些没有声明的变量会订阅到全局对象。
Process
它也是全局对象之一,但包含将同步功能转换为异步回调的其余功能。从代码中的任何地方访问它都没有限制。它是EventEmitter类的实例。每一个node application object
都是Process对象的一个实例。
它主要返回有关应用程序或环境的信息。
<process.execPath>
– 获取Node应用程序的执行路径.<process.Version>
– 获取当前正在运行的Node版本.<process.platform>
– 获取服务器平台.其余一些有用的处理方法以下:
<process.memoryUsage>
– 了解node程序使用的内存.<process.NextTick>
– 附加一个将在下一个循环中调用的回调函数。它会致使函数延迟执行.Buffer
Buffer是Node.js中处理二进制数据的一个类。它相似于整数列表,可是存储在V8堆以外的原始内存中。
咱们能够将JavaScript字符串对象转换为Buffers。但这须要显式地声明编码类型。
<ascii>
– 指定7位ASCII数据.<utf8>
– 表示多字节编码的Unicode字符集.<utf16le>
– 表示2或4个字节,用小尾数编码的Unicode字符.<base64>
– 用于Base64字符串编码.<hex>
– 将每一个字节编码为两个十六进制字符.这是使用Buffer类的语法:
> var buffer = new Buffer(string, [encoding]);
上面的命令将分配一个新的buffer来保存默认编码为 utf8
的字符串。可是,若是您想将string
写入现有的buffer object
,请使用如下代码行:
> buffer.write(string)
buffer 还提供其余方法,例如readInt8
和writeUInt8
,该方法容许从各类类型的数据读/写到 buffer。
要在Node.js中加载HTML,咱们必须将HTML代码中的 Content-type
从 text/plain 更改成 text/html。
让咱们看一个在web服务器中建立静态文件的示例:
fs.readFile(filename, "binary", function(err, file) { if (err) { response.writeHead(500, {"Content-Type": "text/plain"}); response.write(err + "\n"); response.end(); return; } response.writeHead(200); response.write(file, "binary"); response.end(); });
如今,咱们将修改此代码以加载HTML页面而不是纯文本。
fs.readFile(filename, "binary", function(err, file) { if (err) { response.writeHead(500, {"Content-Type": "text/html"}); response.write(err + "\n"); response.end(); return; } response.writeHead(200, {"Content-Type": "text/html"}); response.write(file); response.end(); });
Node.js中的事件模块容许咱们建立和处理自定义事件。事件模块包含 EventEmitter
类,可用于引起和处理自定义事件。可经过如下代码进行访问:
// 导入事件模块 var events = require('events'); // 建立一个eventEmitter对象 var eventEmitter = new events.EventEmitter();
当EventEmitter实例遇到错误时,它将触发 error
事件。添加新的侦听器时,将触发 newListener
事件,而删除侦听器时,将触发 removeListener
事件。
EventEmitter提供多个属性,例如 on
和 emit
。on
属性用于将函数绑定到事件,emit
用于触发事件。
Node.js中的Stream是容许以连续方式从源读取数据或将数据写入特定目标的对象。在Node.js中,有四种类型的流:
<Readable>
– 这是用于读取操做的Stream.<Writable>
– 它简化了写的操做.<Duplex>
– 此流可用于读取和写入操做.<Transform>
– 它是双工流的一种形式,它根据可用的输入执行计算.上面讨论的全部流都是 EventEmitter
类的实例。由流抛出的事件随时间而变化。一些经常使用事件以下:
<data>
– 当有可供读取的数据时,将触发此事件.<end>
– 没有更多数据可读取时,Stream将触发此事件.<error>
– 当读取或写入数据时出现任何错误时触发此事件.<finish>
– 当全部数据刷新到底层系统后,将触发此事件.下面是一些最经常使用的REPL命令:
<.help>
– 显示全部命令的帮助.<tab Keys>
– 它显示全部可用命令的列表.<Up/Down Keys>
– 它的用途是肯定以前在REPL中执行了什么命令.<.save filename>
– 将当前的REPL会话保存到文件中.<.load filename>
– 在当前REPL会话中加载指定的文件.<ctrl + c>
– 用于终止当前命令.<ctrl + c (twice)>
– 退出REPL.<ctrl + d>
– 此命令执行从REPL退出.<.break>
– 从多行表达式导出.<.clear>
– 从多行表达式退出.NPM 是Node的一个包管理器,也是一个平台。它提供如下两个主要功能:
NPM与Node.js捆绑在一块儿安装。咱们可使用如下命令:
# 验证它的版本 $ npm --version # 使用如下命令帮助安装任何Node.js模块。 # $ npm install <Module Name> # 例如,下面是安装一个著名的Node.js web框架模块express-的命令 $ npm install express