美文网首页
JS运行机制复习

JS运行机制复习

作者: baxiamali | 来源:发表于2019-07-30 17:50 被阅读0次

    Js是单线程语言

    原因:作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。避免复杂同步问题。

    消息队列

    JS任务分类:

    1. 同步任务(synchronous)在主线程上排队执行的任务,前一个执行完毕,执行后一个任务。
    2. 异步任务(asynchronous)不进入主线程,进入任务队列(task queue),当任务队列通知主线程,某异步任务可以执行,该异步任务才会进入主线程执行。
    console.log("A");
    while(true){ }
    console.log("B");
    
    console.log("A");
    setTimeout(function(){
    console.log("B");
    },0);
    while(true){}
    

    Event Loop

    image.png
    1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
    2. 主线程之外,还存在一个任务队列(task queue)。只要异步任务有了运行结果,就在任务队列之中放置一个事件。
    3. 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
    4. 主线程不断重复上面的第三步。

    总结:主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。只要主线程空了,就会去读取任务队列

    image.png

    任务队列

    1. setTimeout和setlnterval
    2. DOM事件
    3. ES6中的Promise
    4. Ajax异步请求
    for (var i = 0; i < 5; i++) {
    setTimeout(function() {  
     console.log(i);  
      }, 1000);
    }
    

    浏览器渲染进程

    GUI渲染进程
    1. 负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等。
    2. 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。(前端性能优化点)
    3. 注意,GUI渲染线程与JS引擎线程是互斥的,当JS引擎执行时GUI线程会被挂起(相当于被冻结了),GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
    JS引擎线程
    1. 也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎)
    2. 由于js是单线程(一个Tab页内中无论什么时候都只有一个JS线程在运行JS程序),依靠任务队列来进行js代码的执行,所以js引擎会一直等待着任务队列中任务的到来,然后加以处理。
    3. 同样注意,GUI渲染线程与JS引擎线程是互斥的,所以如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞。
    事件触发线程
    1. 归属于渲染(浏览器内核)进程,不受JS引擎线程控制。主要用于控制事件(例如鼠标,键盘等事件),当该事件被触发时候,事件触发线程就会把该事件的处理函数添加进任务队列中,等待JS引擎线程空闲后执行
    定时触发器线程
    1. setInterval与setTimeout所在线程。
    2. 浏览器的定时器并不是由JavaScript引擎计数的,因为JavaScript引擎是单线程的, 如果处于阻塞线程状态就会影响计时的准确,因此通过单独的线程来计时并触发定时器,计时完毕后,满足定时器的触发条件,则将定时器的处理函数添加进任务队列中,等待JS引擎线程空闲后执行。
    3. W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。
    异步http请求线程
    1. 当XMLHttpRequest连接后,浏览器会新开的一个线程,当监控到readyState状态变更时,如果设置了该状态的回调函数,则将该状态的处理函数推进任务队列中,等待JS引擎线程空闲后执行。
    image.png

    宏任务(macrotask)与微任务(microtask)

    console.log('script start');
    
    setTimeout(function() {
        console.log('setTimeout');
    }, 0);
    
    Promise.resolve().then(function() {
        console.log('promise1');
    }).then(function() {
        console.log('promise2');
    });
    
    console.log('script end');
    

    JS中分为两种任务类型:macrotask和microtask,在ECMAScript中,microtask称为jobs,macrotask可称为task

    image.png
    1. macrotask:主代码块,setTimeout,setInterval等(可以看到,事件队列中的每一个事件都是一个macrotask)
    2. microtask:Promise,process.nextTick,mutation
    3. 补充:在node环境下,process.nextTick的优先级高于Promise,也就是可以简单理解为:在宏任务结束后会先执行微任务队列中的nextTickQueue部分,然后才会执行微任务中的Promise部分。

    相关文章

      网友评论

          本文标题:JS运行机制复习

          本文链接:https://www.haomeiwen.com/subject/ashnrctx.html