zhentaoo / js-tower

前端博客:原站点 zhentaoo.com不在维护了,原有的博客内容迁移至issue,方便大家交流

Home Page:https://github.com/zhentaoo/js-tower/issues

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

事件循环

zhentaoo opened this issue · comments

参考:http://blog.csdn.net/alex8046/article/details/51914205
消息队列:是一个先进先出的队列,它里面存放着各种消息。(消息就是注册异步任务时添加的回调函数。)
事件循环:事件循环是指主线程重复从消息队列中取消息、执行的过程。

用代码表示如下:

while(true) {
    var message = queue.get();
    execute(message);
}

image

异步的过程 :

  1. 主线程发起一个异步请求
  2. 相应的工作线程接收请求并告知主线程已收到(异步函数返回);
  3. 主线程可以继续执行后面的代码,同时工作线程执行异步任务;
  4. 工作线程完成工作后,通知主线程;
  5. 主线程收到通知后,执行一定的动作(调用回调函数)。

从生产者,消费者角度来看异步的过程:

  1. 工作线程是生产者,主线程是消费者(只有一个消费者)。
  2. 工作线程执行异步任务,执行完成后把对应的回调函数封装成一条消息放到消息队列中;
  3. 主线程不断地从消息队列中取消息并执行,当消息队列空时主线程阻塞,直到消息队列再次非空。

JS异步过程:

  1. 由于JavaScript是单线程的,因此所有任务都需要排队
  2. 同步任务会在主线程中执行,形成一个执行栈,栈底是全局上下文,栈顶是当前执行的函数上下文
  3. 主线程如果遇到异步任务,则把该异步任务放置在工作线程(net/fs)中,该异步任务完成后放到task queue中
  4. 等所有同步任务执行完成后,才会执行异步任务
  5. 主线程的event loop会循环遍历task queue,如果发现有异步任务,就会把这个异步任务对应的call back至于执行中并执行

异步模型:

  1. 同步模型:遇到网络IO等耗时较长的操作时,进程会一直等待,导致CPU空闲,整个系统资源被浪费
  2. 多线程模型:在上述情况下,可能会同时等待多个IO请求,导致系统资源被严重浪费
  3. 异步模型:会先把同步任务执行完,把异步任务丢到task queue中,等异步任务完成之后再执行对应的callback

参考:https://cnodejs.org/topic/57d68794cb6f605d360105bf
当Node.js启动时会初始化event loop, 每一个event loop都会包含按如下顺序六个循环阶段,

   ┌───────────────────────┐
┌─>│        timers         │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     I/O callbacks     │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     idle, prepare     │
│  └──────────┬────────────┘      ┌───────────────┐
│  ┌──────────┴────────────┐      │   incoming:   │
│  │         poll          │<─────┤  connections, │
│  └──────────┬────────────┘      │   data, etc.  │
│  ┌──────────┴────────────┐      └───────────────┘
│  │        check          │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
└──┤    close callbacks    │
   └───────────────────────┘
  • timers 阶段: 这个阶段执行setTimeout(callback) and setInterval(callback)预定的callback;
  • I/O callbacks 阶段: 执行除了 close事件的callbacks、被timers(定时器,setTimeout、setInterval等)设定的callbacks-setImmediate()设定的callbacks之外的callbacks;
  • idle, prepare 阶段: 仅node内部使用;
  • poll 阶段: 获取新的I/O事件, 适当的条件下node将阻塞在这里;
  • check 阶段: 执行setImmediate() 设定的callbacks;
  • close callbacks 阶段: 比如socket.on(‘close’, callback)的callback会在这个阶段执行.
console.log(‘1’);

setImmediate(function () {
console.log(‘2’);
});

setTimeout(function () {
console.log(‘3’);
},0);

process.nextTick(function () {
console.log(‘4’);
});

1–4--2–3