什么是观察者?
在深入了解现代浏览器支持的观察者系列之前,让我们先了解一般的观察者是什么?
观察者是一个观察或注意到某事的程序。观察者有助于观察浏览器中发生的某些活动并做出相应的响应。
我们经常处理用 addEventListener 来添加事件监听用户的各种操作,比如:click, mousedown, drag, wheel 等(完整事件列表参考:https://developer.mozilla.org/zh-CN/docs/Web/Events) 。
现代浏览器提供了 5 种 Observer ,使用这些 Observer ,我们可以观察浏览器中发生的不同类型的活动,并采取必要的行动。例如。我们可以观察到,视频是否显示在视口中并启用自动播放,是否已从父 DOM 元素中添加或删除子元素,是否更改了框元素的大小 / 尺寸等等。
以下是现代浏览器支持的五种不同类型的 Observer 。
- Intersection Observer
- Mutation Observer
- Performance Observer
- Resize Observer
- ReportingObserver
Performance Observer
用于观察 Performance Timeline,并在浏览器记录新的性能条目时得到通知。它可用于测量浏览器和 nodejs 应用程序中的某些性能指标。在浏览器中,我们可以使用 Window 对象作为 window.PerformanceObserver 访问观察者,而在 nodejs 应用程序中,我们必须要求 perf_hooks 才能获取性能对象。例如。const { performance } = require(‘perf_hooks’); ** **
它在以下情况下很有用:
- 测量请求和响应之间的处理时间。(在浏览器中)
- 从数据库中检索数据时计算持续时间。(在 nodejs 应用程序中)
- 使用 Paint Timing Api 提取精确的时间信息,例如第一次绘画或第一次内容丰富的绘画时间。
- 使用 User Timing API、Navigation Timing API、Network Information API、Resource Timing API、Paint 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> |