1. 从用户态发出异步I/O调用后,到回调函数被执行,中间发生了什么?
因为Node中的异步I/O调用不是有开发者自己调用的。示例代码如下:
fs.open = function (path, flags, mode, callback) {
	// ...
  binding.open(
    pathModule._makeLong(path), 
    stringToFlags(flags), 
    mode, 
    callback
  );
  // ...
}整个异步I/O的流程如下:
    
    
请求对象、I/O线程池、观察者、 事件循环 这四个共同构成了Node异步I/O模型的基本要素。大致流程:
- 创建FSReqWrap请求对象,包括传参、当前方法、回调函数等都在请求对象中;
 - 将请求对象放入线程池中等待执行;
 - 线程执行完毕后,将结果存储在请求对象中,通知IOCP
 - 事件循环的观察者在每次Tick的执行中,调用IOCP相关方法查看是否有执行完毕的请求
 - 将请求对象放入I/O观察者队列,然后当做事件处理
 
2. Node应用是单线程还是多线程,如何理解?
JavaScript执行是单线程,但是Node本身是多线程的,比如I/O相关操作。
3. 非I/O的异步执行过程?
这里涉及的到异步API包括:setTimeout()、setInterval()、setImmediate()、process.nextTick() 这四个;整个过程以setTimeout()为例:
    
    
- 创建setTimeout时,将定时器插入到定时观察者内部的红黑树中
 - 每次Tick执行是,会从改红黑树中取出定时器对象判定
 - 判定时间到了则执行定时器回调,否则跳过
 
process.nextTick() 与setTimeout(setInterval)类似,只是process.nextTick() 只会将回调函数放入队列中,在下一轮Tick时取出执行。时间效率「O(1)」 比setTimeout「O(logn)」高。
setImmediate()与process.nextTick()类似,但是process.nextTick()的优先级更高;具体来说:
- process.nextTick()回调函数保存在数组中;setImmediate()保存在链表中
 - process.nextTick()每轮循环中会将数组中的回调函数全部执行完;setImmediate()在每轮循环中执行链表的一个回调函数(执行完毕后进入下一轮循环)
 - 
process.nextTick()是idle观察者,setImmediate()是check观察者;
- 优先级:idle观察者 -> I/O观察者 -> check观察者
 
 
- 本文作者:烈风裘
 - 本文题目:Nodejs查漏补缺-异步相关
 - 本文链接:https://xiangst0816.github.io/blog/nodejs-cha-lou-bu-que-yi-bu-xiang-guan/
 - 版权声明:本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!