🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
关于异步 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章中详述。