异步的概念之所以先在Web 2.0中火起来,是因为在浏览器中JavaScriptd在单线程上执行,而且它还和UI渲染共用一个线程。这意味着JavaScript在执行的时候UI渲染和响应是处于停滞状态的。《高性能JavaScript》一书中曾说过,如果脚本的执行时间超过100毫秒,用户就会感到页面卡顿,以为网页停止响应。而在B/S模型中,网络速度的限制给网页的实时体验造成很大的麻烦。如果网页临时需要获取一个网络资源,通过同步的方式获取,那么JavaScript则需要等待资源完全从服务器端获取后才能继续执行,这期间UI将停顿,不响应用户的交互行为。可以想象,这样的用户体验将会多差。而采用异步请求,在下载资源时间,JavaScript和UI的执行都不会处于等待状态,可以继续响应用户的交互行为,给用户一个鲜活的页面。
同理,前端通过异步可以消除掉UI阻塞的现象,但是前端获取资源的速度也取决于后端的响应速度。假如一个资源来自于两个不同位置的数据的返回,第一个资源需要M毫秒的耗时,第二个需要N毫秒的耗时。如果采用同步的方式,代码大致如下:
~~~
// 消费时间为 M
getData('from_db');
// 消费时间为 N
getData('from_remote_api');
~~~
但是如果采用异步方式,第一个资源的获取并不会阻塞第二个资源,也即第二个资源的请求并不依赖第一个资源的结束。如果,我们可以享受到并发的优势,相关代码如下:
~~~
getData('from_db',function(){
// 消费时间为M
});
getData('from_remote_api',function(){
// 消费时间为N
});
~~~
对比两者的时间总消耗,前者为M+N,后者为 max(M,N)。
随着应用复杂性的增加,情景将会变成M+N+... 和max(M,N,...),同步于异步的优劣将会凸显出来。另一方面,随着网站或应用不断膨胀,数据将会分布到多台服务器上,分布式将会是常态。分布也意味着M与N的值会线性增长,这也会放大异步和同步在性能方面的差异。为了让读者感知到M和N值具体多昂贵,下表列出了从CPU一级缓存到网络的数据访问所需要的开销:
![](https://box.kancloud.cn/2016-08-28_57c1cec1a0302.png)
这就是异步I/O在Node中如此盛行,甚至将其作为主要理念进行设计的原因。I/O是昂贵的,分布式I/O是更昂贵的。
只有后端能快速响应资源,才能让前端的体验变好。
- 目录
- 第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 事件驱动与高性能服务器