代码
// 性能警报时间,单位:毫秒,超过这个时间会打印警报,可自定义
const ALARM_TIME = 200;
// requestAnimationFrame的id
let monitorFrameTimeId = null;
/**
* 开始监控帧耗时
*/
function startMonitorFrameTime() {
stopMonitorFrameTime();
// 由于启动监控时当前帧可能已经过了一段时间了,所以等到下一帧开始再启动性能监控
// 如果优先启动监控,也可以去掉外面这一层requestAnimationFrame
monitorFrameTimeId = requestAnimationFrame(() => {
console.log("启动性能监控");
// performance.now()拿到的时间比Date精度更高
let lastTime = performance.now();
monitorFrameTimeId = requestAnimationFrame(callback);
function callback() {
const now = performance.now();
const delta = now - lastTime;
lastTime = now;
if (delta >= ALARM_TIME) {
console.warn(`性能警报,当前帧耗时:${delta.toFixed(2)}ms`);
}
monitorFrameTimeId = requestAnimationFrame(callback);
}
});
}
/**
* 停止监控当前帧耗时
*/
function stopMonitorFrameTime() {
if (monitorFrameTimeId != null) {
console.log("停止性能监控");
cancelAnimationFrame(monitorFrameTimeId);
monitorFrameTimeId = null;
}
}
// 监听切换到后台
// 由于切换到后台会暂停网页绘制,导致两次requestAnimationFrame回调的时间被拉长,所以切后台的时候停止箭头
document.addEventListener("visibilitychange", function () {
// 判断当前页面是否隐藏
// this指向了document,this.hidden等价于document.hidden,如果用了箭头函数这里就不能用this了
if (this.hidden) {
console.log("切换到后台");
stopMonitorFrameTime();
} else {
console.log("切换到前台");
startMonitorFrameTime();
}
});
startMonitorFrameTime();
预览
日志样式也可以根据自己的喜好修改一下:
const titleStyle = [
`background: #d35400`,
"padding: 0.2em 0.2em 0.2em 0.2em",
`color: #ffffff`,
"font-size: 1em",
"border-radius: 0.2em 0 0 0.2em",
"font-family: SimHei",
].join("; ");
const contentStyle = [
`background: #e67e22`,
"padding: 0.2em 0.2em 0.2em 0.2em",
`color: #ffffff`,
"font-size: 1em",
"border-radius: 0 0.2em 0.2em 0",
"font-family: SimHei",
].join("; ");
console.log("%c%s%c%s", titleStyle, "性能管理器", contentStyle, `性能警报,当前帧耗时:${delta.toFixed(2)}ms`);