关于异步 I/O ,向前端工程师解释起来或许会容易一些,因为发起Ajax调用对于前端工程师而言是再熟悉不过的场景了。下面的代码用于发起一个Ajax请求:
~~~
$.post('/url', {title:'深入浅出Node.js'}, function(data){
console.log('收到响应');
})
console.log('发送Ajax结束');
~~~
熟悉异步的用户必然知道,“收到响应”是在“发送Ajax结束”之后输出的。在调用 $.post() 后,后续代码是被立即执行的,而“收到响应”的执行时间是不被预期的。我们只知道它将在这个异步请求结束后执行,但并不知道具体时间点。异步调用中对于结果值的捕获是符合“Don't call me,I will call you”的原则的,这也是注重结果,不关心过程的一种表现。下图是一个经典的Ajaxe调用:
![](https://box.kancloud.cn/2016-08-25_57bdc8fa78718.png)
在Node中,异步 I/O 也很常见。以读取文件为例,我么可以看到它与前端Ajax调用的方式是极其类似的:
~~~
const fs = require('fs');
fs.readFile('/etc/passwd',(err, data)=>{
if(err) throw err;
console.log('读取文件完成');
})
console.log('发起读取文件');
~~~
这里的“发起读取文件”是在“读取文件完成”或 throw err 之前输出的。同样,“读取文件完成”或 throw err 执行,也取决于读取文件的异步调用何时结束。下图是一个经典的异步调用:
![](https://box.kancloud.cn/2016-08-25_57bdc8faa7b29.png)
在Node中,绝大多数的操作都是以异步的方式进行调用。Ryan Dahl排除万难,在底层构建了很多异步 I/O 的API,从文件读取到网络请求等,均是如此。这样的意义在于,在Node中,我们可以从语言层面很自然的进行 并行 I/O 操作。每个调用之间无需等待之前的 I/O 调用结束。在编程模型上可以极大提升效率。
下面的两个文件读取任务的耗时,取决于最慢的那个文件读取的耗时:
~~~
fs.readFile('/path1',(err, data)=>{
console.log('读取文件1完成');
});
fs.readFile('/path2',(err, data)=>{
console.log('读取文件2完成');
});
~~~
而对于同步 I/O 而言,它们的耗时是两个任务的耗时之和。这里异步带来的优势是显而易见的。
关于异步I/O 如何提升效率及其本身的机制和实现,我们将在第3章中详述。
- 目录
- 第1章 Node 简介
- 1.1 Node 的诞生历程
- 1.2 Node 的命名与起源
- 1.2.1 为什么是 JavaScript
- 1.2.2 为什么叫 Node
- 1.3 Node给JavaScript带来的意义
- 1.4 Node 的特点
- 1.4.1 异步 I/O
- 1.4.2 事件与回调函数
- 1.4.3 单线程
- 1.4.4 跨平台
- 1.5 Node 的应用场景
- 1.5.1 I/O 密集型
- 1.5.2 是否不擅长CPU密集型业务
- 1.5.3 与遗留系统和平共处
- 1.5.4 分布式应用
- 1.6 Node 的使用者
- 1.7 参考资源
- 第2章 模块机制
- 2.1 CommonJS 规范
- 2.1.1 CommonJS 的出发点
- 2.1.2 CommonJS 的模块规范
- 2.2 Node 的模块实现
- 2.2.1 优先从缓存加载
- 2.2.2 路径分析和文件定位
- 2.2.3 模块编译
- 2.3 核心模块
- 2.3.1 JavaScript核心模块的编译过程
- 2.3.2 C/C++核心模块的编译过程
- 2.3.3 核心模块的引入流程
- 2.3.4 编写核心模块
- 2.4 C/C++扩展模块
- 2.4.1 前提条件
- 2.4.2 C/C++扩展模块的编写
- 2.4.3 C/C++扩展模块的编译
- 2.4.2 C/C++扩展模块的加载
- 2.5 模块调用栈
- 2.6 包与NPM
- 2.6.1 包结构
- 2.6.2 包描述文件与NPM
- 2.6.3 NPM常用功能
- 2.6.4 局域NPM
- 2.6.5 NPM潜在问题
- 2.7 前后端共用模块
- 2.7.1 模块的侧重点
- 2.7.2 AMD规范
- 2.7.3 CMD规范
- 2.7.4 兼容多种模块规范
- 2.8 总结
- 2.9 参考资源
- 第3章 异步I/O
- 3.1 为什么要异步I/O
- 3.1.1 用户体验
- 3.1.2 资源分配
- 3.2 异步I/O实现现状
- 3.2.1 异步I/O与非阻塞I/O
- 3.2.2 理想的非阻塞异步I/O
- 3.2.3 现实的异步I/O
- 3.3 Node的异步I/O
- 3.3.1 事件循环
- 3.3.2 观察者
- 3.3.3 请求对象
- 3.3.4 执行回调
- 3.3.5 小结
- 3.4 非I/O的异步API
- 3.4.1 定时器
- 3.5 事件驱动与高性能服务器