相关概念
异步I/O与非阻塞I/O
操作系统内核对IO
- 阻塞:应用程序需要等待IO完成才返回结果
- 非阻塞:不带数据直接返回(返回仅仅是当前调用的状态),要获取数据需要通过文件描述符再次读取(重新判断操作是否完成:轮询)
轮询技术
- read
- select
- poll
- epoll
理想非阻塞异步IO
应用程序发起非阻塞调用,无须通过便利或事件唤醒等方式轮询,可以直接处理下一任务,只需在IO完成后通过信号或回调将数据传递给应用程序即可
现实异步IO
~nix:自定义线程池
Window:IOCP 调用异步方法,等待IO完成之后的通知,执行回调,用户无需考虑轮询
node平台提供libuv作为抽象封装层,使得所有平台兼容性的判断都有这一层来完成,保证上层node与下层自定义线程池及IOCP之间各自独立
node的异步IO
关键词 单线程、事件循环、观察者和IO线程池
node异步模型的基本要素 事件循环、观察者、请求对象和IO线程池
事件循环
观察者
判断是否有事件需要处理 事件循环是一个典型的生产者/消费者模型。事件被传递到对应的观察者那里,事件循环则从观察者那里取出事件并处理
请求对象
请求对象是异步IO过程中的重要中间产物,所有状态都保存在这个对象中,包括送入线程池等待执行以及IO操作完毕后的回调处理
执行回调
异步IO第一步:组装好请求对象、送入IO线程池等待执行 第二步:回调通知
非IO的异步API
定时器
setTimeout() setInterval()
创建定时器插入定时器观察者内部的一个红黑树中。每次Tick执行时会从红黑树中迭代取出定时器对象,检查是否超过定时时间,如果超过就形成一个事件,回调函数立即执行 问题在于:它并不精确
process.nextTick()
会将回调函数放入队列中,下一轮Tick是取出执行 ……