事件循环(EventLoop)

事件循环(EventLoop)

JavaScript是单线程语言,JavaScript中的任务分为同步任务(sync task)和异步任务(async task)。遇到执行函数会将其放入调用栈(先进后出)中,遇到setTimeout/setInterval等异步任务时,会把它放入到消息队列中,等主线程的任务执行完成以后,再回过头执行消息队列中的异步任务,如果异步任务中仍然有异步任务,会继续放入消息队列,以此类推,便形成了一个事件循环。

同步任务:在主线程上排队。
异步任务:在任务队列中排队,等待通知进入主线程执行。

事件循环执行过程

  1. 所有同步任务都在主线程上执行,形成一个执行栈。
  2. 主线程之外存在一个任务队列,js引擎会将异步任务的完成事件存入该队列等待主线程读取。
  3. 执行栈中的同步任务都执行完毕后,js引擎会读取执行任务队列中的任务。
  4. 主线程不断循环重复以上第三步。

任务队列(task queue)

任务队列可以看做是消息队列,耗时长的任务比如读写磁盘、ajax、或者比如带有callback的事件等完成后就会在任务队列中添加事件,表示该任务可以进入执行栈。

异步任务必须指定callback,当任务队列中的事件被主线程读取时就会执行回调函数。

主线程中的堆(heap)和栈(stack)

heap and stack:

eventloop

主线程运行时产生堆和栈,栈中的代码调用很多外部的API,这些API在任务队列中添加各种事件。栈中的代码执行完毕,主线程就会读取任务队列中的事件执行回调函数。

执行栈中的代码总是在读取任务队列之前被执行。

定时器(timer)

  • setTimeout
  • setInterval

这两个函数只有在当前执行栈清空后才会执行callback。

setTimeout(fn, 0) 含义是:fn会等到同步任务和任务队列中的任务都处理完才会被执行。
实际上:setTimeout最短延迟时间为4ms。

评论