• 宏任务和微任务


    宏任务和微任务

            微任务 --- microtask称为jobs, 宏任务 --- macrotask称为task,  宏任务是由宿主发起的,而微任务由JavaScript自身发起。

    常见的面试题

    console.log('start')
    
    setTimeout(()=>{
       console.log('setTimeout')
    },0)
    
    new Promise((resolve)=>{
       console.log("promise");
       resolve();
    }).then(()=>{
       console.log("then1");
    }).then(()=>{
       console.log("then2");
    })
    
    console.log("end");

    它的顺序是

    start 
    promise
    end
    then1
    then2
    setTimeout
    

      

    实践

      解:

      Event Loop中,每一次循环称为tick,每一次tick的任务如下:

      执行栈选择最先进入队列的宏任务,执行其同步代码直至结束;

      检查是否存在微任务,有则会执行微任务队列为空;

      如果宿主为浏览器,可能会渲染页面;

      开始下一轮tick,执行宏任务中的异步代码;

      setImmediate 和 process.nextTick 为Node环境下常用的方法,所以基于Node宿主分析。

      ( Node.js是运行在服务端的js,虽然用到也是v8引擎,但由于服务目的和环境不同,导致了它的API和原生JS有些区别,其EventLoop还要处理一些I/O,比如新的网络连接等。)

      执行顺序如下:

         1、timers: 执行setTimeout和setInterval的回调。

         2、pending callbacks:执行延迟到下一个循环迭代的I/O回调。

         3、idle prepare:仅系统内部使用。

         4、poll:检索新的I/O事件;执行与I/O事件相关的回调。

         5、check: setImmediate在这里执行。

         6、close callbacks: 一些关闭的函调函数

     setImmediate和setTimeout

    console.log("outer");
    setTimeout(() => {
         setTimeout(() => {
            console.log("setTimeout");
         },0);
    
         setImmediate(() => {
            console.log("setImmediate")
          })
    },0)

      其执行顺序为:

       1、外层是一个setTimeout,所以执行它的回调函数已经在timers阶段了。

       2、处理里边的setTimeout,因为本次循环的timers正在执行,所以其回调其实加到了下一级timers阶段

       3、处理里边的setImmediate,将它的回调加入check阶段的队列。

       4、外层timers阶段处理完,进入pending callbacks,idle,prepare,poll,这几个队列都是空的,所以继续住下到了check阶段,发现了setImmediate的回调,拿出来执行

       5、然后是close callbacks,队列是空的,跳过

         

      在Node里边对setTimeout的特殊处理,setTimeout(fn, 0)会被强制改为setTimeout(fn, 1)

          1、遇到setTimeout,虽然设置的是0毫秒触发,但是被node.js强制改为1毫秒,塞入timers阶段。

          2、遇到setImmediate塞入check阶段。

          3、同步代码执行完毕,进入Event  Loop

          4、先进入timers阶段,检查当前时间过去了1毫秒没有,如果过了1毫秒,满足setTimeout条件,执行回调,如果没过14毫秒,跳过。

          5、跳过空的阶段,进入check阶段,执行setImmediate

         可见,1毫秒是个关键点,所以,setImmediate不一定在setTimeout之前执行了。

       promise 和 process.nextTick

       因为 process.nextTick 为node环境下的方法,是一个特殊的异步API,其不属于任何的Event Loop阶段。

       事实上Node在遇到这个API时,Event Loop根本不会继续进行,会马上停下来执行process.nextTick( ), 这个执行完才会继续Event Loop。所以,nextTick 和 Promise 同时出现,肯定是nextTick先执行,原因是nextTick的队列比Promise队列优先级更高。

       vue实例的nextTick( )方法接受一个回调函数作为参数,用于将回调延迟到下次DOM更新周期之后执行。这个API就是基于事件循环实现的。下次DOM更新就是下次微任务执行时更新DOM,而vm.$nextTick就是将回调函数添加到微任务中。

    未完,待续......
  • 相关阅读:
    PHP工程师学Python数据类型
    通过PHP与Python代码对比浅析语法差异
    “adobe premiere中画面和声音不同步” 解决方法
    Web安全之XSS Platform搭建及使用实践
    使用docker快速搭建Permeate渗透测试系统实践
    Web安全开发规范手册V1.0
    遭受刷验证码攻击后的企安建设规划感想
    基于Docker搭建Jumpserver堡垒机操作实践
    使用PHP结合Ffmpeg快速搭建流媒体服务实践
    通过代码审计找出网站中的XSS漏洞实战(三)
  • 原文地址:https://www.cnblogs.com/zhishiyv/p/14626630.html
Copyright © 2020-2023  润新知