面试语述:JS事件轮询机制(Event Loop)

先上一段面试题:请写出以下代码console的顺序是什么?
你可以先不要看下面的内容,认真的先自己写一遍答案出来,看看自己是否能写出答案来。

setTimeout(() => {
  console.log("setTimeOut start");
  new Promise((resolve) => {
    console.log("promise1 start");
    resolve();
  }).then(() => {
    console.log("promise1 end");
  });
  console.log("setTimeout end");
}, 0);

function promise2() {
  return new Promise((resolve) => {
    console.log("promise2");
    resolve();
  });
}
async function async1() {
  console.log("saync1 start");
  await promise2();
  console.log("saync1 end");
}
async1();
console.log("script end");

现在你可以在你的项目代码script里面把这段代码复制进去执行一下,或者复制到浏览器控制台里运行一下,对一下你的答案是否是正确的。

现在你可以背一个js执行顺序口诀:先同步 后异步 先微观 再宏观

一、js 是单线程执行的

js中的任务按顺序一个一个的执行,但是一个任务耗时太长,那么后面的任务就需要等待,为了解决这种情况,将任务分为了同步任务和异步任务,而异步任务又可以分为微任务和宏任务

二、概念

1.宏任务:当前调用栈中执行的代码成为宏任务。(主代码快,定时器等等)。
2.微任务:当前(此次事件循环中)宏任务执行完,在下一个宏任务开始之前需要执行的任务,可以理解为回调事件。(promise.then,proness.nextTick等等)。
3.宏任务中的事件放在callback queue中,由事件触发线程维护;微任务的事件放在微任务队列中,由js引擎线程维护。

三、运行机制
  1. 在执行栈中执行一个宏任务。
  2. 执行过程中遇到微任务,将微任务添加到微任务队列中。
  3. 当前宏任务执行完毕,立即执行微任务队列中的任务。
  4. 当前微任务队列中的任务执行完毕,检查渲染,GUI线程接管渲染。
  5. 渲染完毕后,js线程接管,开启下一次事件循环,执行下一次宏任务(事件队列中取)。
四、微任务和宏任务

微任务:process.nextTick、MutationObserver、Promise.then catch finally
宏任务:I/O、setTimeout、setInterval、setImmediate、requestAnimationFrame

五、流程

1、同步和异步任务分别进入不同的执行“场所”,同步进入主线程,异步进入Event Table并注册函数。
2、当指定的事情完成时,Event Table会将这个函数移入Event Queue。主线程内的任务执行完毕为空,回去了Event Queue读取对应的函数,进入主线程。
3、上述过程会不断重复,也就是常说的Event Loop(事件循环)。
4、但是,JS异步还有一个机制,就是遇到宏任务,先执行宏任务,将宏任务放入event queue,然后再执行微任务,将微任务放入eventqueue,但是,这两个queue不是一个queue。当你往外拿的时候先从微任务里拿这个回调函数,然后再从宏任务的queue拿宏任务的回调函数。

现在我们来看看我们运行的结果现在是否能理解清楚了


代码划分一下.jpg

然后运行后的答案就是:


代码运行一下.jpg
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容