PerformanceEventTiming
事件计时 API 的 PerformanceEventTiming
接口提供了对由用户交互触发的某些事件类型的延迟的见解。
描述
此 API 通过为某些事件类型提供事件时间戳和持续时间(参见下文)来使缓慢事件可见。例如,您可以监视用户操作与其事件处理程序开始之间的时间,或事件处理程序运行所需的时间。
此 API 特别适用于测量 首次输入延迟 (FID):从用户首次与您的应用程序交互的时刻到浏览器实际能够响应该交互的时刻之间的时间。
您通常通过创建 PerformanceObserver
实例,然后调用其 observe()
方法(将 "event"
或 "first-input"
作为 type
选项的值传递)来使用 PerformanceEventTiming
对象。然后,PerformanceObserver
对象的回调将使用 PerformanceEventTiming
对象列表调用,您可以分析这些对象。有关更多信息,请参见 下面的示例。
默认情况下,PerformanceEventTiming
条目在其 duration
为 104 毫秒或更大时公开。研究表明,在 100 毫秒内未处理的用户输入被认为是缓慢的,而 104 毫秒是大于 100 毫秒的 8 的第一个倍数(出于安全原因,此 API 四舍五入到最接近的 8 毫秒倍数)。但是,您可以使用 observe()
方法中 durationThreshold
选项将 PerformanceObserver
设置为不同的阈值。
此接口从其父级 PerformanceEntry
继承方法和属性
公开的事件
事件计时 API 公开以下事件类型
请注意,以下事件未包含在列表中,因为它们是连续事件,并且目前无法获得有意义的事件计数或性能指标:mousemove
、pointermove
、pointerrawupdate
、touchmove
、wheel
、drag
。
要获取所有公开事件的列表,您也可以在 performance.eventCounts
映射中查找键
const exposedEventsList = [...performance.eventCounts.keys()];
构造函数
此接口本身没有构造函数。有关如何通常获取 PerformanceEventTiming
接口保存的信息,请参见 下面的示例。
实例属性
此接口通过以下方式扩展了以下 PerformanceEntry
属性,用于事件计时性能条目类型
PerformanceEntry.duration
只读-
返回一个
DOMHighResTimeStamp
,表示从startTime
到下一个渲染绘制的时间(四舍五入到最接近的 8 毫秒)。 PerformanceEntry.entryType
只读-
返回
"event"
(对于长事件)或"first-input"
(对于第一次用户交互)。 PerformanceEntry.name
只读-
返回关联事件的类型。
PerformanceEntry.startTime
只读-
返回一个表示关联事件的
DOMHighResTimeStamp
的timestamp
属性。 这是事件创建的时间,可以看作用户交互发生时间的代理。
此接口还支持以下属性
PerformanceEventTiming.cancelable
只读-
返回关联事件的
cancelable
属性。 PerformanceEventTiming.interactionId
只读 实验性-
返回唯一标识触发关联事件的用户交互的 ID。
PerformanceEventTiming.processingStart
只读-
返回一个表示事件调度开始时间的
DOMHighResTimeStamp
。 要衡量用户操作时间与事件处理程序开始运行时间之间的间隔,请计算processingStart-startTime
。 PerformanceEventTiming.processingEnd
只读-
返回一个表示事件调度结束时间的
DOMHighResTimeStamp
。 要衡量事件处理程序运行时间,请计算processingEnd-processingStart
。 PerformanceEventTiming.target
只读-
如果关联事件的最后一个目标没有被移除,则返回它。
实例方法
PerformanceEventTiming.toJSON()
-
返回
PerformanceEventTiming
对象的 JSON 表示。
示例
获取事件计时信息
要获取事件计时信息,请创建一个 PerformanceObserver
实例,然后调用其 observe()
方法,并将 "event"
或 "first-input"
作为 type
选项的值传入。 您还需要将 buffered
设置为 true
以获取用户代理在构建文档时缓冲的事件。 然后,PerformanceObserver
对象的回调将被调用,并带有一个 PerformanceEventTiming
对象列表,您可以分析这些对象。
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
// Full duration
const duration = entry.duration;
// Input delay (before processing event)
const delay = entry.processingStart - entry.startTime;
// Synchronous event processing time
// (between start and end dispatch)
const eventHandlerTime = entry.processingEnd - entry.processingStart;
console.log(`Total duration: ${duration}`);
console.log(`Event delay: ${delay}`);
console.log(`Event handler duration: ${eventHandlerTime}`);
});
});
// Register the observer for events
observer.observe({ type: "event", buffered: true });
您还可以设置不同的 durationThreshold
。 默认值为 104 毫秒,最小可能的持续时间阈值为 16 毫秒。
observer.observe({ type: "event", durationThreshold: 16, buffered: true });
报告首次输入延迟 (FID)
首次输入延迟或 FID,测量从用户首次与页面交互(例如,当他们单击链接或点击按钮时)到浏览器实际能够开始处理响应该交互的事件处理程序的时间。
// Keep track of whether (and when) the page was first hidden, see:
// https://github.com/w3c/page-visibility/issues/29
// NOTE: ideally this check would be performed in the document <head>
// to avoid cases where the visibility state changes before this code runs.
let firstHiddenTime = document.visibilityState === "hidden" ? 0 : Infinity;
document.addEventListener(
"visibilitychange",
(event) => {
firstHiddenTime = Math.min(firstHiddenTime, event.timeStamp);
},
{ once: true },
);
// Sends the passed data to an analytics endpoint. This code
// uses `/analytics`; you can replace it with your own URL.
function sendToAnalytics(data) {
const body = JSON.stringify(data);
// Use `navigator.sendBeacon()` if available,
// falling back to `fetch()`.
(navigator.sendBeacon && navigator.sendBeacon("/analytics", body)) ||
fetch("/analytics", { body, method: "POST", keepalive: true });
}
// Use a try/catch instead of feature detecting `first-input`
// support, since some browsers throw when using the new `type` option.
// https://webkit.org/b/209216
try {
function onFirstInputEntry(entry) {
// Only report FID if the page wasn't hidden prior to
// the entry being dispatched. This typically happens when a
// page is loaded in a background tab.
if (entry.startTime < firstHiddenTime) {
const fid = entry.processingStart - entry.startTime;
// Report the FID value to an analytics endpoint.
sendToAnalytics({ fid });
}
}
// Create a PerformanceObserver that calls
// `onFirstInputEntry` for each entry.
const po = new PerformanceObserver((entryList) => {
entryList.getEntries().forEach(onFirstInputEntry);
});
// Observe entries of type `first-input`, including buffered entries,
// i.e. entries that occurred before calling `observe()` below.
po.observe({
type: "first-input",
buffered: true,
});
} catch (e) {
// Do nothing if the browser doesn't support this API.
}
规范
规范 |
---|
事件计时 API # sec-performance-event-timing |
浏览器兼容性
BCD 表仅在浏览器中加载