zoukankan      html  css  js  c++  java
  • 浏览器

    浏览器的构成

    用户界面:地址栏,后退/前进按钮,书签目录等;(除了从服务器请求到的网页的窗口)

    浏览器引擎:用来查询及操作渲染引擎的接口;

    渲染引擎:用来显示请求的html内容;   

    网络:主要是来完成网络调用,例如http请求,它具有平台无关的接口,可以在不同平台上工作;

    UI后端:用来绘制类似组合选择框及对话框等基本组件,具有不特定于某个平台的通用接口,底层使用操作系统的用户接口。

    JS解释器 :用来解释执行JS代码;

    数据存储:属于持久层,浏览器需要在硬盘中保存类似cookie的各种数据,HTML5定义了web database技术,这是一种轻量级完整的客户端存储技术;

    浏览器的进程

    Browser进程:浏览器的主进程,只有一个。主要有以下功能:

    • 负责浏览器界面显示,与用户交互。如前进,后退等
    • 负责各个页面的管理,创建和销毁其他进程
    • 网络资源的管理,下载等

    第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建;

    GPU进程:最多一个,用于3D绘制;

    浏览器渲染进程:默认每个Tab页面一个进程,互不影响,控制页面渲染,脚本执行,事件处理等(有时候会优化,如多个空白tab会合并成一个进程);

    如图:

    浏览器的渲染进程(浏览器内核)

    通常说的浏览内核指的是浏览器的渲染引擎和js引擎

    浏览器内核,即我们的渲染进程,我们页面的渲染,js的执行,事件的循环都在这一进程内进行。该进程下面拥有着多个线程,靠着这些线程共同完成渲染任务。这些线程如下:

    1 图形用户界面GUI渲染线程

    • 负责渲染浏览器界面,包括解析HTML、CSS、构建DOM树、Render树、布局与绘制等
    • 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行

    2  JS引擎线程

    • JS引擎,负责处理执行javascript脚本
    • 等待任务队列的任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS引擎在运行JS程序

    3 事件触发线程

    • 这部分不属于JS引擎,其实归属于浏览器,用来控制事件循环(可以理解,JS引擎自己都忙不过来,需要浏览器另开线程协助);
    • 当JS引擎执行代码块如setTimeout时(也可来自浏览器内核的其他线程,如鼠标点击、AJAX异步请求等),会将对应任务添加到事件线程中
    • 当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理
    • 注意:由于JS的单线程关系,所以这些待处理队列中的事件都得排队等待JS引擎处理(当JS引擎空闲时才会去执行)

    4 定时触发器线程

    • setIntervalsetTimeout所在线程
    • 定时计时器并不是由JS引擎计时的,因为如果JS引擎是单线程的,如果JS引擎处于堵塞状态,那会影响到计时的准确
    • 当计时完成被触发,事件会被添加到事件队列,等待JS引擎空闲了执行
    • 注意:W3C的HTML标准中规定,setTimeout中低与4ms的时间间隔算为4ms

    5 异步HTTP请求线程

    • 在XMLHttpRequest在连接后新启动的一个线程
    • 线程如果检测到请求的状态变更,如果设置有回调函数,该线程会把回调函数添加到事件队列,同理,等待JS引擎空闲了执行

    渲染进程(浏览器内核)的线程如下:

    渲染进程中的线程之间的关系

    GUI渲染线程与JS引擎线程互斥

    因为JS引擎可以修改DOM树,那么如果JS引擎在执行修改了DOM结构的同时,GUI线程也在渲染页面,那么这样就会导致渲染线程获取的DOM的元素信息可能与JS引擎操作DOM后的结果不一致。为了防止这种现象,GUI线程与JS线程需要设计为互斥关系,当JS引擎执行的时候,GUI线程需要被冻结,但是GUI的渲染会被保存在一个队列当中,等待JS引擎空闲的时候执行渲染。
    由此也可以推出,如果JS引擎正在进行CPU密集型计算,那么JS引擎将会阻塞,长时间不空闲,导致渲染进程一直不能执行渲染,页面就会看起来卡顿卡顿的,渲染不连贯,所以,要尽量避免JS执行时间过长。

    JS引擎线程与事件触发线程、定时触发器线程、异步HTTP请求线程

    事件触发线程、定时触发器线程、异步HTTP请求线程三个线程有一个共同点,那就是使用回调函数的形式,当满足了特定的条件,这些回调函数会被执行。这些回调函数被浏览器内核理解成事件,在浏览器内核中拥有一个事件队列,这三个线程当满足了内部特定的条件,会将这些回调函数添加到事件队列中,等待JS引擎空闲执行。例如异步HTTP请求线程,线程如果检测到请求的状态变更,如果设置有回调函数,回调函数会被添加事件队列中,等待JS引擎空闲了执行。
    但是,JS引擎对事件队列(宏任务)与JS引擎内的任务(微任务)执行存在着先后循序,当每执行完一个事件队列的时间,JS引擎会检测内部是否有未执行的任务,如果有,将会优先执行(微任务)。

    WebWorker

    因为JS引擎是单线程的,当JS执行时间过长会页面阻塞,那么JS就真的对CPU密集型计算无能为力么?

    所以,后来HTML5中支持了Web Worker

    Web Workers 使得一个Web应用程序可以在与主执行线程分离的后台线程中运行一个脚本操作。这样做的好处是可以在一个单独的线程中执行费时的处理任务,从而允许主(通常是UI)线程运行而不被阻塞/放慢。

    所以,如果需要进行一些高耗时的计算时,可以单独开启一个WebWorker线程,这样不管这个WebWorker子线程怎么密集计算、怎么阻塞,都不会影响JS引擎主线程,只需要等计算结束,将结果通过postMessage传输给主线程就可以了。

    原文:

    https://segmentfault.com/a/1190000013083967

  • 相关阅读:
    腾讯云 Serverless 产品动态 20200827
    双指针 86. 分隔链表(链表 dummyhead)
    双指针:15. 三数之和
    双指针:283. 移动零
    双指针:167. 两数之和 II
    关于数组
    关于抽象类,接口以及多态
    关于字符串
    关于异常
    动手动脑3
  • 原文地址:https://www.cnblogs.com/xjy20170907/p/12615230.html
Copyright © 2011-2022 走看看