Skip to content

浏览器原理

面试02题库-浏览器

浏览器的主要功能

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

浏览器的主要组成部分是什么?

  1. 用户界面 - 包括地址栏、前进/后退按钮、书签菜单等。除了浏览器主窗口显示的您请求的页面外,其他显示的各个部分都属于用户界面。
  2. 浏览器引擎 - 在用户界面和呈现引擎之间传送指令。
  3. 呈现引擎(Tab页签) - 负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。
  4. 网络 - 用于网络调用,比如 HTTP 请求。其接口与平台无关,并为所有平台提供底层实现。
  5. 用户界面后端 - 用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层使用操作系统的用户界面方法。
  6. JavaScript 解释器(V8引擎)。用于解析和执行 JavaScript 代码。
  7. 数据存储。这是持久层。浏览器需要在硬盘上保存各种数据,例如 Cookie。新的 HTML 规范 (HTML5) 定义了“网络数据库”,这是一个完整(但是轻便)的浏览器内数据库。

图:浏览器的主要组件。

值得注意的是,和大多数浏览器不同,Chrome 浏览器的每个标签页都分别对应一个呈现引擎实例。每个标签页都是一个独立的进程。

👆 这些引擎的概念先不细究,我们需要明确了解的是,浏览器每个页签都是一个单独的进程,每个进程里都有各自的渲染线程、V8线程、worker线程等

同时,Tab下的所有线程并不是互斥,只有V8线程和渲染线程互斥,其他线程可以并行如worker线程

单线程概念

JS的所有处理都是 V8线程 单线程处理的,也就是 JS 的执行不存在并发

同时浏览器让页签进程里的渲染线程和V8线程互斥,也是另一种单线程的说法

JS 异步是 V8引擎 利用消息队列延后排队处理的一种机制,并不等于并发

🌰 输入框

输入框需要渲染引擎实时渲染,但是此时接入 JS逻辑,渲染引擎 和 V8引擎 互斥就可能出现渲染卡顿

此时可以把 JS逻辑中的耗时逻辑拆分成异步,就不会影响 input 的实时渲染,当然异步出去的 JS逻辑 只是在排队,并没有消失,所以还可以优化重复事件的节流

🌰 进度条需求

html
<div id="progress"></div>

<script>
  function count() {
    for (let i = 0; i < 1e6; i++) {
      i++;
      progress.innerHTML = i;
    }
  }
  count();
</script>

👆 没有异步任务,只有在V8线程执行完成,才会交由渲染线程进行渲染

也就是页面将从 直接显示为 1000000, 不会随着遍历实时渲染

渲染线程和V8线程的交替机制

同步任务 -> 微任务 -> 渲染引擎 -> 宏任务 -> 微任务 -> 渲染引擎

👇 正因如此 同样的进度条需求把同步任务拆分为异步任务的微任务

html
<div id="progress"></div>
<script>
  let i = 0;
  function count() {
    // 做繁重的任务的一部分 (*)
    do {
      i++;
      progress.innerHTML = i;
    } while (i % 1e3 != 0);

    if (i < 1e6) {
      queueMicrotask(count); // <-- this
    }
  }
  count();
</script>

会等所有微任务执行完成,才触发渲染引擎,因此页面依然从 直接显示为 1000000, 不会随着遍历实时渲染

👇 而 每个宏任务后都会执行微任务以及渲染引擎

html
<div id="progress"></div>

<script>
  let i = 0;
  function count() {
    // 做繁重的任务的一部分 (*)
    do {
      i++;
      progress.innerHTML = i;
    } while (i % 1e3 != 0);

    if (i < 1e6) {
      setTimeout(count);
    }
  }
  count();
</script>

注意 requestAnimationFrame() run code before the next rendering cycle

同样可以实现实时渲染,它强制告诉浏览器——执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画

因此同步任务未执行完成,也会执行回调事件触发并交由渲染引擎