有人问 logTimingOnce 是 JS 内置什么函数——不是。这个名字不是浏览器标准 API,也不在 Node 内置里。多半是:
- 某个项目里自己定义的工具函数
- 某个框架 / SDK 内部封装
- 被压缩混淆后的名字
从名字看是 log + Timing + Once——只记录一次耗时日志。列几种可能的实现和前端性能计时的正规做法。
猜测的实现
版本 1:一次性计时器
function logTimingOnce(name, fn) {
const start = performance.now();
const result = fn();
const end = performance.now();
console.log(`${name}: ${(end - start).toFixed(2)}ms`);
return result;
}
// 用法
const data = logTimingOnce("parseJSON", () => JSON.parse(bigStr));
版本 2:同一 key 只打一次
const logged = new Set();
function logTimingOnce(key, cost) {
if (logged.has(key)) return;
logged.add(key);
console.log(`[timing] ${key}: ${cost}ms`);
}
// 用法
const start = performance.now();
initWebGL();
logTimingOnce("webgl-init", performance.now() - start); // 只打一次
大型 SPA / 游戏 / WebGL / AI 前端里这种模式常见——首屏耗时、初始化时间只统计一次。
想知道具体项目里 logTimingOnce 是哪种,直接:
console.log(logTimingOnce.toString());
正规姿势:performance.now
Date.now() 精度只到毫秒,且系统时钟被调整还会跳(NTP 校时、用户改时间)。计时永远用 performance.now():
const start = performance.now();
// ... 做事
const cost = performance.now() - start;
console.log(cost); // 精度到微秒(0.001ms)
单调时钟,不会倒退,浏览器和 Node 都支持。
User Timing API:让 DevTools 看得见
上面的 console.log 输出到控制台,看着乱。用 User Timing API 把标记打到 Performance 面板:
performance.mark("webgl-init-start");
initWebGL();
performance.mark("webgl-init-end");
performance.measure(
"webgl-init",
"webgl-init-start",
"webgl-init-end"
);
之后 Chrome DevTools → Performance 面板里能看到 webgl-init 这条竖线,跟其它内置事件(LCP、FCP)在一起。
拿测量结果:
const [entry] = performance.getEntriesByName("webgl-init");
console.log(entry.duration);
PerformanceObserver:订阅性能事件
要监听所有 measure(比如上报到日志系统):
const observer = new PerformanceObserver(list => {
for (const entry of list.getEntries()) {
console.log(entry.name, entry.duration);
// 上报到你的日志服务
}
});
observer.observe({ entryTypes: ["measure"] });
也能监听浏览器内置事件:
// LCP(Largest Contentful Paint)
new PerformanceObserver(list => {
const last = list.getEntries().pop();
console.log("LCP:", last.startTime);
}).observe({ type: "largest-contentful-paint", buffered: true });
常用性能指标一览
| 指标 | 什么意思 | 怎么拿 |
|---|---|---|
| FCP (First Contentful Paint) | 首次有内容渲染 | paint entryType |
| LCP (Largest Contentful Paint) | 最大内容渲染 | largest-contentful-paint |
| FID (First Input Delay) / INP | 首次 / 最长交互延迟 | event、first-input |
| CLS (Cumulative Layout Shift) | 布局偏移 | layout-shift |
| TTFB (Time to First Byte) | 首字节时间 | navigation entryType |
想一次性拿 Web Vitals,直接用 Google 的库:
npm install web-vitals
import { onCLS, onLCP, onINP } from "web-vitals";
onCLS(console.log);
onLCP(console.log);
onINP(console.log);
顺带:JS 生成 UUID
原对话里还问了 UUID,顺便说下——现代浏览器和 Node 直接用:
crypto.randomUUID();
// "3f6c2a6f-8d7d-4f9c-b7d5-3fcb52c8a1aa"
比自己写的 Math.random 版本安全(用 CSPRNG)、代码短。老浏览器不支持时才需要 polyfill。
一句话总结
logTimingOnce 是项目自定义函数,不是标准 API。真正测性能用 performance.now() 做基础,performance.mark/measure 让 DevTools 看得见,PerformanceObserver 采集上报。UUID 直接 crypto.randomUUID()。
