JS的事件循环

事件循环

关于事件循环,首先需要了解四个概念。

  1. 同步与异步
  2. 阻塞与非阻塞

1.同步与异步同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用的结果。而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。

2.阻塞与非阻塞阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态. 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

然后JS是单线程异步非阻塞的。始终是非阻塞的(alert除外)。那么就存在一个问题,JS如何处理并行操作,毕竟单线程意味着它一次只能处理一件事情,答案是通过事件循环。

浏览器

如图可以看见堆,栈以及消息队列。重点关注执行栈和消息队列。

对于主线程的运行就应该像是这样:

首先执行被推入栈的函数,同时将这个已经被执行的函数(因为JS是异步非阻塞的,所以并不会认为得到了函数的返回才算是将函数执行完成)清理出栈。当执行栈变得干净了以后主线程得到空闲以后,就去执行消息队列,然后处理完消息队列以后继续检查栈。

这里的消息指的是被指定的异步操作完成以后应该执行的回调函数。

同时消息队列也分为两类。微任务(micro task)和宏任务(macro task)。微任务始终在宏任务之前执行。

以下事件属于宏任务:

  • setInterval()
  • setTimeout()

以下事件属于微任务

  • new Promise()
  • new MutaionObserver()

Node

对于Node,它引入了一个新的事件循环模型

   ┌───────────────────────┐
┌─>│        timers         │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     I/O callbacks     │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     idle, prepare     │
│  └──────────┬────────────┘      ┌───────────────┐
│  ┌──────────┴────────────┐      │   incoming:   │
│  │         poll          │<──connections───     │
│  └──────────┬────────────┘      │   data, etc.  │
│  ┌──────────┴────────────┐      └───────────────┘
│  │        check          │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
└──┤    close callbacks    │
   └───────────────────────┘
  1. 外部输入数据
  2. 轮询阶段(poll)
  3. 检查阶段(check)
  4. 关闭事件回调阶段(close callback)
  5. 定时器检测阶段(timer)
  6. I/O事件回调阶段(I/O callbacks)
  7. 闲置阶段(idle, prepare)
  8. 轮询阶段...

这些阶段大致的功能如下:

  • timers: 这个阶段执行定时器队列中的回调如 setTimeout() 和 setInterval()。
  • I/O callbacks: 这个阶段执行几乎所有的回调。但是不包括close事件,定时器和setImmediate()的回调。
  • idle, prepare: 这个阶段仅在内部使用,可以不必理会。
  • poll: 等待新的I/O事件,node在一些特殊情况下会阻塞在这里。
  • check: setImmediate()的回调会在这个阶段执行。
  • close callbacks: 例如socket.on('close', ...)这种close事件的回调。
原文地址:https://www.cnblogs.com/freesfu/p/12760865.html