zoukankan      html  css  js  c++  java
  • 18 JS的事件循环,以及微任务和宏任务。

    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

  • 相关阅读:
    Golang之字符串格式化
    BZOJ 4513: [Sdoi2016]储能表 [数位DP !]
    BZOJ 3329: Xorequ [数位DP 矩阵乘法]
    BZOJ 1833: [ZJOI2010]count 数字计数 [数位DP]
    HDU2089 不要62 BZOJ1026: [SCOI2009]windy数 [数位DP]
    未完
    [Miller-Rabin & Pollard-rho]【学习笔记】
    BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
    BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]
    BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]
  • 原文地址:https://www.cnblogs.com/hacker-caomei/p/14128925.html
Copyright © 2011-2022 走看看