JS基础--EventLoop
Posted IT职业地图
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS基础--EventLoop相关的知识,希望对你有一定的参考价值。
这个话题面试必备,了解js运行机制前端进阶知识。
1.同步 Vs 异步
在了解event loop之前,我们认清同步和异步两个概念。我们都知道js是单线程的,同步的意思就是:同步的代码(或函数)必须执行完毕,再继续执行下一行代码(或函数)。异步的意思:执行到异步代码(或函数)时,不用等待异步代码(或函数)的执行完毕,继续向下执行。举个例子: 你喊女票吃饭,女票换衣服,化妆等用去30分钟,这30分钟你只能等待(等待函数结束返回),不能自己先去吃饭,这就是同步。你女票喊你吃饭,不管你做什么反应,女票不等你(不用等待函数返回,继续执行下面的代码),独自往饭店走,这就是异步。
2.消息队列 & Event loop
那么问题来了,说好的js是单线程呢?异步函数怎么执行的呢?
先介绍几个概念:
主线程(执行栈):js的函数统一在主线程中执行,是一个先进先出的栈;
事件/任务(task):一个异步函数的“执行(回调)函数”被压入事件队列时称为一个任务(task);
事件队列/任务队列(Task Queue宏任务队列):宏任务(macrotasks)暂时存放的队列;
微任务队列(Microtask Queue):microtasks暂时存放的队列(最新的概念称之为job)。
Macrotasks 和 Microtasks的划分如下:
Macrotasks: setTimeout,setInterval, setImmediate, I/O, UI渲染;
Microtasks: Promise.then ,process.nextTick, Object.observe, MutationObserver。
执行顺序:
主线程执行栈开始顺序执行一个函数内代码段;
遇到同步函数直接执行,遇到异步函数时放入对应的队列;
同步代码完成后,先检查Microtask Queue队列;
检查Microtask Queue队列是否为空,不为空,执行e,如果为空,执行f;
将Microtask Queue的首个task弹出,并压入主线程中执行(从b开始),执行后,重复d;
再检查Task Queue队列是否为空,不为空,执行g,如果为空,执行h;
将Task Queue的首个task弹出,并压入主线程中执行(从b开始),执行后,重复f;
当Microtask Queue 和 Task Queue 同时为空,此函数返回,主线程继续执行顺序执行新函数。
向这种主线程从"任务队列"中读取事件,这个过程是循环不断的,这种运行机制又称为EventLoop(事件循环)。如图:
先来一个简单点的想下输出结果是什么:
思路:
1.在主线程执行本代码段时,遇见同步的console.log直接执行;
2.将setTimeout 放入宏事件队列,将promise.then放入微事件队列。 new promise构造函数是同步的,所以最先开始执行同步代码打印结果是: start, new promise, end;
3.然后查看微循环队列,执行2个promise.then,分别打印new promise then 和 promise then;
4.最后查看宏事件队列,打印 setTimeout。
我们来看下最终结果:
复杂代码:
这个思路一样,就是多了几层异步而已。请小伙伴们自己试试。
执行结果:
记住eventloop的执行过程及Microtask 和 Macrotask的区别就可以很清晰判断代码的执行顺序。
参考文章:http://www.ruanyifeng.com/blog/2014/10/event-loop.html
https://juejin.im/post/5aacd1766fb9a028cb2d6766
http://www.cnblogs.com/dong-xu/p/7000139.html
欢迎补充和指正,感谢关注《IT职业地图》
以上是关于JS基础--EventLoop的主要内容,如果未能解决你的问题,请参考以下文章