最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 2019.12.08-Week-JavaScript执行过程

    正文概述 掘金(进击的大羊)   2021-01-14   390

    1.事件循环

    JavaScript运行是单线程的,浏览器在执行js脚本的时候,当js中的一环报错或者出现死循环,就不会再继续往下执行了,直到这个问题被解决。

    相关概念

    • 队列机制

    JavaScript提供了一种机制,会将所有的定时器都放到一个队列里面,当主线程的代码执行完成之后再执行队列里面的代码

    • 宏任务

    所有在主线程上执行的任务(除了异步函数以外的所有任务); 对应的微任务即:异步函数/异步任务

    • 异步函数

    如果一个异步函数被调用时,该函数会立即返回,尽管该函数规定的操作任务还没有完成

    js执行过程

    • 首先执行宏任务 ,当执行宏任务的时候,如果发现有定时器任务时,会将定时器添加到宏任务的任务队列里面,继续完成宏任务;
    • 当宏任务完成后,会检查是否有微任务:如果有,则执行后,再回到微任务,如果没有,则回到宏任务;
    • 检查任务队列里有没有未完成的任务,如果有,则继续执行,执行后,结束js脚本的执行;如果没有则结束js脚本的执行。
    setTimeout( () => console.log(4))
    
    new Promise(resolve => {
      resolve()
      console.log(1)
    }).then( () => {
      console.log(3)
    })
    
    Promise.resolve(5).then(() => console.log(5))
    console.log(2)
    
    // 输出结果为:1,2,3,5,4
    

    上述执行过程为:

    1. 首先执行同步代码,第一行的 setTimeout 是异步代码,跳过,来到了 new Promise(...) 这一段代码。这种方式是一个构造函数,是一个同步代码,所以执行同步代码里面的函数,即 console.log(1)
    2. 接下来是一个 then 的异步,跳过。再往下,是一个Promise.then() 的异步,跳过。最后一个是一段同步代码 console.log(2)。所以,第一轮打印了1, 2两个值。
    3. 接下来进入下一步,即异步代码。从上往下,第一个是 setTimeout,还有两个是 Promise.then()setTimeout 是宏任务的异步,Promise.then()是微任务的异步,微任务是优先于宏任务执行的,
    4. 所以,此时会先跳过 setTimeout 任务,执行两个 Promise.then() 的微任务。所以此时会执行 console.log(3) console.log(5) 两个函数,最后执行 console.log(4)

    事件循环Event Loop

    EventLoop是一个执行模型,在不同的有不同的实现,浏览器和NodeJS基于不同的技术实现了各自的EventLoop2019.12.08-Week-JavaScript执行过程

    执行宏任务的同步任务,在主线程上形成一个执行栈,查看执行栈是否为空,如果执行栈为空,就会去检查微任务队列是否为空,如果为空的话,就执行Task(宏任务),否则就一次性执行完所有微任务。

    每次单个宏任务执行完毕后,检查微任务队列是否为空,如果不为空的话,会按照先入先出的规则全部执行完微任务后,设置微任务队列为null,然后再执行宏任务,如此循环。

    2.执行环境

    浏览器的Event loop是在HTML5中定义的规范,而node中则由libuv库实现。libuv库流程大体分为6个阶段:timers,I/O callbacks,idle、prepare,poll,check,close callbacks,和浏览器的microtaskmacrotask有区别。两者执行的规则不同,所以不相同。

    • 浏览器的EventLoop是在HTML5规范中明确定义了的

    NodeJS的EventLoop是基于libuv实现的。可以在libuv官网和NodeJS官网查看

    • libuv已经对NodeJSEventLoop做出了实现,但是浏览器的HTML5规范只是定义了EventLoop的实现模型,具体的实现留给了浏览器厂商。

    3.宏任务(macrotask )和微任务(microtask )

    在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 macrotask 的队列(这个队列也被叫做 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的所有任务顺序执行;之后再取 macrotask 任务,周而复始,直至两个队列的任务都取完。

    宏任务的主要工作

    • 创建主文档对象,解析HTML,执行主线或者全局的javascript的代码,更改url以及各种事件
    • 页面加载,输入,网络事件,定时器。从浏览器角度看,宏任务是一个个离散的,独立的工作单元
    • 运行完成后,浏览器可以继续其他调度,重新渲染页面的UI或者去执行垃圾回收

    一些异步任务的回调会以此进入 macrotask queue(宏任务队列),等等后续被调用,这些异步函数包括:setTimeout,setInterval,setImmediate (Node),requestAnimationFrame (浏览器),I/O,UI rendering (浏览器).

    微任务的工作

    • 微任务是更小的任务,微任务更新应用程序的状态,但是必须在浏览器任务继续执行其他任务之前执行,浏览器任务包括重新渲染页面的UI。
    • 微任务包括Promise的回调函数,DOM发生变化等,微任务需要尽可能快地,通过异步方式执行,同时不能产生全新的微任务。
    • 微任务能使得我们能够在重新渲染UI之前执行指定的行为,避免不必要的UI重绘,UI重绘会使得应用状态不连续
    • 另一些异步回调会进入 microtask queue(微任务队列) ,等待后续被调用,这些异步函数包括:process.nextTick (Node),Promise.then(),catch,finally,Object.observe,MutationObserver.

    4.总结

    由于浏览器引擎负责解释和执行JavaScript的主线程是单线程,同步执行一个耗时较大的任务会导致阻塞。

    异步执行代码可以解决阻塞问题,但会带来顺序的不确定性,如果这些任务彼此不相关,就不一定需要交互,如果没有相互影响的话,不确定性是完全可以接受的。

    如果你需要保证异步执行的顺序,比如依次远程读取一系列url, 按顺序触发动画等,就需要嵌套很多层回调函数。

    多级嵌套的回调函数弊端很多:不直观,强耦合,回调的不确定性,不利于维护与复用等。所以才有promise等异步执行的相关方法,保证执行的顺序性。


    起源地下载网 » 2019.12.08-Week-JavaScript执行过程

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元