js运行机制:eventloop(事件循环),看了很多博客的讲解,我也想自己总结一些这个知识点。

 

JavaScript的事件分为同步和异步

首先第一点,js永远是单线程的,以后也是。

使用单线程原因:如果多线程,一个线程删除元素,一个线程修改元素会造成混乱。

使用单线程问题:如果一个任务等待的时间非常久,在这中间会有cpu闲置,1会浪费时间,2会浪费资源。

解决办法:同步和异步。

同步任务:主线程执行的任务。 

异步任务:不进入主线程,而是进入任务队列,任务队列通知主线程,某个可以执行了,就可以执行。

(1)所有同步任务都在主线程上执行(console.log(),for循环,new Process里面),形成一个执行栈(execution context stack)。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

"任务队列":除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。

"回调函数"(callback):就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。

 

JavaScript的任务分为微任务(Microtasks)和宏任务(task)

0 涉及到的数据结构有什么?

数据结构:1stack 执行栈。 2 宏任务队列。3 微任务队列。

 

1 执行规则是什么?

  答:执行规则:

  1 第一个宏任务入栈执行,遇到宏任务放在宏任务队列里面,遇到微任务放在当前微任务队列里面,遇到同步代码放在栈里面执行。(注意放的是回调函数!)

  2 第一个宏任务执行完,会找到微任务队列,给微任务队列说,该你执行了,微任务队列把自己队列里面的任务全部执行完。

  3微任务队列执行结束。如果还有宏任务,就继续执行宏任务回到1。没有的话就结束。

 

2 微任务宏任务都有谁啊?

1宏任务(macro task): 1整个代码(scirpt),2定时器 (setTimeout ,setImmediate),3事件绑定setInterval,4ajax,5回调函数,6Node中fs可以进行异步的I/O操作

2 微任务(micro task):promise.nextTick,promise.then(),  async await。

3 直接执行的有:console.log(),new Process里面的。

 

3 都是异步代码为什么还要区分宏任务,微任务啊?如何区分宏任务和微任务呢?划分的标准是什么?

 

在ES3以及以前的版本中,JavaScript本身没有发起异步请求的能力,也就没有微任务的存在。在ES5之后,JavaScript引入了Promise,这样,不需要浏览器,JavaScript引擎自身也能够发起异步任务了。

两者区别为:宏任务是由宿主发起的,而微任务由JavaScript自身发起。

 宏任务(macrotask)微任务(microtask)
谁发起的 宿主(Node、浏览器) JS引擎
具体事件 1. script (可以理解为外层同步代码)
2. setTimeout/setInterval
3. UI rendering/UI事件
4. postMessage,MessageChannel
5. setImmediate,I/O(Node.js)
1. Promise
2. MutaionObserver
3. Object.observe(已废弃;Proxy 对象替代)
4. process.nextTick(Node.js)
谁先运行 后运行 先运行
会触发新一轮Tick吗 不会

 

 

宏任务和微任务的一句话总结:
  • 宏任务 Macrotasks 就是参与了事件循环的异步任务。
  • 宏任务 Macrotasks 就是不参与事件循环的异步任务。
宏任务本质:参与了事件循环的任务。
回到 Chromium 中,需要处理的消息主要分成了三类:
  • Chromium 自定义消息
  • Socket 或者文件等 IO 消息
  • UI 相关的消息
1. 与平台无关的消息,例如 setTimeout 的定时器就是属于这个
2.Chromium 的 IO 操作是基于 libevent 实现,它本身也是一个事件驱动的库
3.UI 相关的其实属于 blink 渲染引擎过来的消息,例如各种 DOM 的事件
其实与 JavaScript 的引擎无关,都是在 Chromium 实现的。

 

微任务本质:直接在 Javascript 引擎中的执行的,没有参与事件循环的任务。
  1. 是个内存回收的清理任务,使用过 Java 的童鞋应该都很熟悉,只是在 JavaScript 这是V8内部调用的
  2. 就是普通的回调,MutationObserver 也是这一类
  3. Callable
  4. 包括 Fullfiled 和 Rejected 也就是 Promise 的完成和失败
  5. Thenable 对象的处理任务

 

宏任务,微任务的优先级

 

promise 是在当前脚本代码执行完后,立刻执行的,它并没有参与事件循环,所以它的优先级是高于 setTimeout。这也就是为什么先执行微任务的优先队列。

 

 

3 为什么整个代码(scirpt)在宏任务里面?

   答:因为一开始需要一个执行机制啊,而且先把所有的同步代码执行完,异步代码放入队列。所以优先级别最高!

 

建议先看视频    b站  :https://www.bilibili.com/video/BV12Z4y1p7Zd?from=search&seid=15652075497796620445

https://www.bilibili.com/video/BV1Hp4y1Y7h7?from=search&seid=15652075497796620445

建议再看图文版  知乎:https://zhuanlan.zhihu.com/p/26238030 

详解宏任务和微任务:

简书:https://www.jianshu.com/p/bfc3e319a96b

博客园:https://www.cnblogs.com/mfyngu/p/11747533.html

掘金的两个大佬:

https://juejin.cn/post/6903338967656366094

https://juejin.cn/post/6844903512845860872#heading-2

csdn:

https://blog.csdn.net/xiaojinguniang/article/details/82985471

https://blog.csdn.net/qq_40323256/article/details/104553150

 

学后练习:

https://blog.csdn.net/weixin_42420703/article/details/82790942

 

三个大佬的补充,我还没有看完:

sf:https://segmentfault.com/a/1190000014940904

 博客园:https://www.cnblogs.com/jiasm/p/9482443.html

posted on 2020-12-13 16:13  程序员草莓  阅读(164)  评论(0编辑  收藏  举报