美文网首页
浏览器工作原理

浏览器工作原理

作者: 莹莹宋 | 来源:发表于2020-10-20 01:17 被阅读0次
    • 为什么js是单线程,web works是多线程?
    • 为什么js单线程却拥有异步?
    • event loop?
    • 为什么setTimeout时间时间不准确

    浏览器的主要功能就是向服务器发出请求,在浏览器窗口中展示您选择的网络资源。这里所说的资源一般是指 HTML 文档,也可以是 PDF、图片或其他的类型。资源的位置由用户使用 URI(统一资源标示符)指定。

    浏览器的高层结构

    用户界面:地址栏,浏览器页面前进后退,刷新和停止刷新按钮,书签...
    浏览器引擎:用户界面与呈现引擎之间传送指令
    呈现引擎:显示请求内容,解析html&css
    网络:网络调用。
    用户界面后端:用户绘制基本的小窗口部件
    JS解释器:用于解析和执行js代码
    数据存储:浏览器在硬盘上保存的各种数据。

    浏览器是多进程的

    浏览器设置中可以找到浏览器的任务管理


    任务管理器.png

    可以看每个页面都是独立的进程,


    任务管理器1.png
    进程分一下几种:
    • 主进程:主进程,只有一个
    • 浏览器渲染进程:进程之间互不影响
    • 第三方插件进程:使用时创建进程
    • GPU进程:用于3D绘制

    浏览器输入网页之后发生了什么?

    呈现引擎示意图(webkit举例)


    webkit.png
    • 呈现引擎解析html文档,讲标记转化成‘树’,同时解析外包css文件。

    • 创建呈现树,包含视觉属性(颜色和尺寸),排列顺序就是屏幕展示顺序

    • 呈现树中每个节点应该出现在屏幕的确切坐标

    • 为了更好的用户体验,引擎会力求尽快将内容展示在屏幕上。

    • 解析器遇到<script>标记时会立即解析脚本,直到资源加载完成,也可以通过添加’defer‘,这样不会停止文档解析。

    • 网络操作与以上同时进行。

    • js解析,由单独的脚本引擎解析执行,通常状态是动态的改变dom树,如果js是多线程,当两个线程同时修改同一个dom节点,下达两个矛盾的命令时,浏览器的执行就成了问题
      以上解决了为什么js是单线程,web works是多线程?

    为什么js单线程却拥有异步?
    单线程是指cpu一次只能做一件事,js在任务队列中提取任务放到主任务中执行,浏览器为异步任务单独开辟线程。就不得不说到Event Loop。

    Event Loop

    JS是单线程的,当遇到大量任务或耗时任务时会卡死,线程大部分事件都在空等I/O的返回结果。这种方式称之为’同步‘。
    Event Loop解决了此类问题,在程序中设置两个线程,一个主线程,负责程序本身的运行,一个另一个负责与其他线程之间的通信。
    首先要了解常用宏任务,微任务
    宏任务:

    • setTimeout
    • setInterval
      微任务
    • Promise
    • nextTick(node)
      Event Loop流程:
    • 执行全局同步代码,调用栈清空
    • 取出微任务队列首位任务,放入调用栈中。直到全部微任务执行完成。
    • 取出宏任务队列首位任务,放入调用栈中执行,其中产生的微任务放入微任务队列,宏任务同理。
    • 重复二三步操作,直到全部执行完成。
    setTimeout(()=>{
        console.log('time1');
        Promise.resolve().then(()=>{
            console.log('p1')
        })
    })
    setTimeout(()=>{
        console.log('time2');
        Promise.resolve().then(()=>{
            console.log('p2')
        })
    })
    

    如图

    event loop 网图
    setTimeout时间时间不准确 :很多原因都会导致setTimeout 没有按时执行,原因之一异步执行setTimeout,将setTimeout放入宏任务栈队列,等执行到宏任务队列时,代码移出本轮事件循环,等到下一轮事件循环,再检查是否到了指定时间。所以会有一定程度的延迟。
    var date = new Date();
    setTimeout(()=>{
      new Promise(
          function (resolve, reject) {
               setTimeout(resolve)
          }
        ).then(()=>{
            console.log(new Date()-date,'p');
        })
    })
    setTimeout(function(e) {
        console.log(new Date()-date,'s');
    });
    

    输出1 "s" 3 'p'
    虽然setTimeout中没有设置时间,但还是延迟执行了一段时间。

    在浏览器中,setTimeout()/setInterval() 的每调用一次定时器的最小间隔是4ms(摘自MDN),也会导致setTimeout没有按时执行

    例如:

    var date = new Date();
    setTimeout(function() {
        setTimeout(function() {
            setTimeout(function() {
                setTimeout(function() {
                    setTimeout(function() {
                        setTimeout(function() {
                            console.log(new Date()-date);
                        }, 0);
                    }, 0);
                }, 0);
            }, 0);
        }, 0);
    }, 0);
    

    如果每个间隔是4ms,输出应该是20,实际输出是16 17 ...,实践证明其实间隔不一定是4ms

    setTimeout(function(){console.log('4');},4)
    setTimeout(function(){console.log('3');},3)
    setTimeout(function(){console.log('2');},2)
    setTimeout(function(){console.log('1');},1)
    setTimeout(function(){console.log('0');},0)
    

    以上代码你觉得会输出什么?
    实际输出 1 0 2 3 4,不同浏览器输出结果不同,每次输出结果也有可能不同。
    是因为,setTimeout在宏任务队列中,主线程按顺序执行宏任务队列,发现没有可以执行的宏任务,遍历队伍有没有可以执行的任务,4ms时间还没到,每次挂起一个settimeout的时候都会循环一遍事件队列。1比0先执行是因为1先被挂起。

    参考资料

    浏览器的工作原理:新式网络浏览器幕后揭秘:https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/#Event_loop
    什么是 Event Loop?阮一峰
    http://www.ruanyifeng.com/blog/2013/10/event_loop.html
    MDN:
    https://developer.mozilla.org/zh-CN/docs/Web/API/Window/setTimeout

    相关文章

      网友评论

          本文标题:浏览器工作原理

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