什么是观察者?
在深入了解现代浏览器支持的观察者系列之前,让我们先了解一般的观察者是什么?
观察者是一个观察或注意到某事的程序。观察者有助于观察浏览器中发生的某些活动并做出相应的响应。

我们经常处理用 addEventListener 来添加事件监听用户的各种操作,比如:click, mousedown, drag, wheel 等(完整事件列表参考:https://developer.mozilla.org/zh-CN/docs/Web/Events) 。

现代浏览器提供了 5 种 Observer ,使用这些 Observer ,我们可以观察浏览器中发生的不同类型的活动,并采取必要的行动。例如。我们可以观察到,视频是否显示在视口中并启用自动播放,是否已从父 DOM 元素中添加或删除子元素,是否更改了框元素的大小 / 尺寸等等。

以下是现代浏览器支持的五种不同类型的 Observer 。

  1. Intersection Observer
  2. Mutation Observer
  3. Performance Observer
  4. Resize Observer
  5. ReportingObserver

Performance Observer
用于观察 Performance Timeline,并在浏览器记录新的性能条目时得到通知。它可用于测量浏览器和 nodejs 应用程序中的某些性能指标。在浏览器中,我们可以使用 Window 对象作为 window.PerformanceObserver 访问观察者,在 nodejs 应用程序中,我们必须要求 perf_hooks 才能获取性能对象。例如。const { performance } = require(‘perf_hooks’); ** **
它在以下情况下很有用:

  • 测量请求和响应之间的处理时间。(在浏览器中)
  • 从数据库中检索数据时计算持续时间。(在 nodejs 应用程序中)
  • 使用 Paint Timing Api 提取精确的时间信息,例如第一次绘画或第一次内容丰富的绘画时间。
  • 使用 User Timing APINavigation Timing APINetwork Information APIResource Timing APIPaint Timing API 访问性能指标

PerformanceObserver 的实现需要三个步骤
a) 创建观察者
只需调用其构造函数并传递处理函数即可创建。

const observer = new PerformanceObserver(logger);

b) 定义目标对象以观察
observer.observe (..) 方法接受可以观察的有效条目类型集。这些入口类型可能属于各种性能 API,例如用户计时或导航计时 API。有效的 entryType 值为:[ USER-TIMING ]、[ USER-TIMING ]、[ NAVIGATION-TIMING-2 ]、[ RESOURCE-TIMING ]。"mark”"measure""navigation""resource"

const config = {
 entryTypes: [“mark”, “measure”]
};
observer.observe(config);

c) 定义回调处理
程序 只要在应用程序中使用观察到的事件,就会触发回调处理程序。例如。它可以用来标记瞬间和测量从开始到结束瞬间的持续时间。

function getDataFromServer() {
 performance.mark(“startWork”); // see [USER-TIMING]
 doWork(); // Some developer code
 performance.mark(“endWork”);
 performance.measure(“start to end”, “startWork”, “endWork”);
 const measure = performance.getEntriesByName(‘start to end’)[0];
 }
function logger(list, observer) {
 const entries = list.getEntries();
 entries.forEach((entry) => {
 console.log(“Name:+ entry.name +
, Type:+ entry.entryType +
, Start:+ entry.startTime +
, Duration:+ entry.duration + “\n”);
 });
}

使用 PerformanceObserver api 的简单演示。
当用户单击一个按钮时,它会将时刻标记为 ** 开始 **_ * 和 *** 结束_**,并测量 3000 毫秒后的持续时间。可以在控制台中查看输出。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      button {
        background: purple;
        color: white;
        cursor: pointer;
        display: inline-block;
        font-size: 20px;
        padding: 1.75rem 1rem;
        text-align: center;
        text-decoration: none;
        font-weight: bold;
        margin-right: 5px;
      }
    </style>
  </head>
  <body>
    <button>测试性能</button>
    <p>* 注意打开控制台查看输出</p>
    <script>
      if (!("PerformanceObserver" in window)) {
        document.body.innerText = "Not supported by your browser";
      }
      /* Initialize performance observer */
      const observer = new PerformanceObserver(logger);
      const config = {
        entryTypes: ["mark", "measure"],
      };
      observer.observe(config);
      /* Callback function */
      function logger(list, observer) {
        const entries = list.getEntries();
        console.log("Entries: ", entries);
        entries.forEach((entry) => {
          console.log(
            "Name: " +
              entry.name +
              ", Type: " +
              entry.entryType +
              ", Start: " +
              entry.startTime +
              ", Duration: " +
              entry.duration +
              "\n"
          );
        });
      }
      /* Add click listener on button */
      document.querySelector("button").addEventListener("click", () => {
        console.log("Start measuring");
        getDataFromServer();
      });
      function getDataFromServer() {
        window.performance.mark("start");
        setTimeout(() => {
          window.performance.mark("end");
          window.performance.measure("start to end", "start", "end");
          const measure = performance.getEntriesByName("start to end")[0];
          window.performance.clearMeasures(["start to end"]);
          window.performance.clearMarks(["start", "end"]);
          //console.log("Duration: ",measure.duration);
        }, 3000);
      }
    </script>
  </body>
</html>