深度剖析JavaScript事件循环机制(未完善)

众所周知,JavaScript 语言采用的是单线程模型。即所有任务只能在一个线程上完成,一次只能做一件事。虽然在 html5 中提出了 Web-Worker ,但这并未改变 JavaScript 是单线程这一核心。
可是,任何一个程序在执行的时候,都可能会开启多个任务,JavaScript也一样,那它怎么处理这种多任务的情况呢?
答案是,JS通过异步的方式来处理多任务,异步的具体方式是通过事件循环(Event Loop)来实现的。
来看下面这段 JavaScript 代码:

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');

先猜测一下执行上面代码输出的顺序是什么,再去执行一下看看你的猜测和结果是否一致。如果一致,说明你对JavaScript事件循环机制有一定的了解,继续往下看可以复习巩固;如果不一致,那么本文下面部分会给你答案。

事件循环的组成分两个部分:执行栈事件队列

执行栈

执行栈,英文Call Stack,也叫调用栈
执行栈用于组织JS代码,保障JS代码的有序执行。每当调用一个函数时,都会在执行栈中加入一个与之对应的执行期上下文,这个上下文定义了该函数执行时的环境,加入执行上下文之后,在执行函数。当函数执行后出栈,执行下一个。

事件队列

事件队列,英文Event Queue,也叫任务队列
所有的任务可以分为同步任务和异步任务,同步任务就是立即执行的任务,同步任务一般会直接进入到执行栈中执行;而异步任务,就是异步执行的任务,比如ajax网络请求,setTimeout 定时函数等都属于异步任务,异步任务会通过任务队列的机制来进行协调。
任务队列在不同的宿主环境中有所差异,大部分宿主环境会将任务队列分成macrotask(宏任务) 和 microtask(微任务)
macrotask主要包含:script( 整体代码)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 环境)
microtask主要包含:Promise、MutaionObserver、process.nextTick(Node.js 环境)

当执行栈清空时,JS引擎首先会将微任务中的所以任务依次执行结束,如果没有微任务了,则执行宏任务。


参考文献

  1. 深入理解JavaScript事件循环
  2. 2分钟了解 JavaScript Event Loop
  3. JavaScript微任务与宏任务、异步、事件循环与消息队列理解

你可能感兴趣的:(深度剖析JavaScript事件循环机制(未完善))