但是异步对性能提升、对用户体验有了革命性的提高,所以NodeJS的 异步特性相当明显,今天我们就来简单学习
异步I/O
其实在操作系统层面上,只有两种I/O方式,堵塞和非堵塞
在堵塞模型中,应用程序需要等待I/O完成才返回结果,他的特点是调用后腰等待系统完成所有操作才行,这个会造成CPU的等待,而非堵塞调用后会马上返回
我初学是看的是一本书,但是这里感觉没有描述清楚,而且异步模型来说其实很大只是感受层面的提高,举一个简单的例子
我现在有一个搜索页和列表页两个单页应用的view,我搜索时候就是需要通过各种渠道搜索,深圳需要调用第三方,第三方再从具体渠道获取数据
这个时候当然很慢,我如果直接由A切入B在B在搞一个loading框什么的加载数据自然没有问题,但是现在问题是我A切换到B需要动画效果
这个就要求切换时候Bview渲染已经结束,至少不会再运到过程中获取数据开始渲染,所以此时异步可能就不那么好使,就是是异步请求数据,也是要数据获取才能加载页面
这个仍然是堵塞加载,这个在业务上是没有办法的
任何技术皆非完美,堵塞造成CPU等待浪费,非堵塞打乱逻辑不说可能还需要轮询以确认是否完成加载(曾经我使用轮询检测一个dom是否生成)
NodeJs采用的是事件循环机制,在进程启动时,Node会创建一个死循环,每执行一次循环体的过程就是一次Tick,每个Tick的过程就是才看是否有事件需要处理
如果有就取出事件相关,执行之,然后进入下一逻辑,没有就退出循环
每个Tick过程中,每个事件循环中有一个或者多个观察者,判断是否有事件要处理的过程就是向这些观察者询问是否需要处理这个事件
以我们html的事件模型为例
对html来说,其实他的每个DOM都是一个观察者,页面的DOM观察着我们的Web Page的变化,我们对一个DOM提供一个addEventListener后,便会对其注册一个回调函数,我们注册的事件会被放到一个“容器”对象中,这时只是注册,这些函数在满足条件后会被触发(页面变化时),相关的事件会从容器中取出执行
我们现在点击了一次页面上一个点,然后我们会由容器中取出click事件集合,我们会找到相关的dom,然后触发这些dom的回调函数
事件可能来自用户的点击或者数据变化,在Node中事件主要来自于网络请求,文件I/O,这些事件都会有对应的观察者,如文件观察者,网络观察者
这也是一个典型生产/消费模型,异步I/O ,网络请求提供事件生产,事件传递到各个观察者,观察者注册事件,事件循环负责取出事件然后执行事件
PS:以click为例,各个DOM观察者先注册事件,页面进程不停的监视页面,用户click页面生产事件,然后由容器中取出注册的click事件并执行,
一般的函数逻辑由我们控制:
var forEach = function (list, callback) {
for (var i = 0, len = list.length; i < len; i++) {
callback(list[i], i, list);
}
}