0

让我们通过来自www.w3.org的注释进行介绍,其中包括两个比较重要的链接。

PerformanceTiming 接口在[NAVIGATION-TIMING]中定义,现在被认为已过时。支持使用 PerformanceTiming 接口中的名称以保持向后兼容,但没有计划将来将此功能扩展到 [NAVIGATION-TIMING-2](或其他接口)中定义的 PerformanceNavigationTiming 接口中的名称。

我已经制作了一个函数来获取应该向后和向前兼容的导航时间,因为我们正处于转换到级别 2 的中间时代。所以这个从事件名称中获取时间的函数在 Chrome 中有效,但在 Firefox 中无效:

function nav(eventName) {
  var lev1 = performance.timing; //deprecated unix epoch time in ms since 1970
  var lev2 = performance.getEntriesByType("navigation")[0]; //ms since page started to load. (since performance.timing.navigationStart)
  var nav = lev2 || lev1; //if lev2 is undefined then use lev1
  return nav[eventName]
}

说明:当没有“导航”条目时,这会退回到基于Unix 纪元时间(自 1970 年以来以毫秒为单位)的已弃用方式进行导航计时(lev1),而新方式(lev2)是自当前以来的HR 时间(以毫秒为单位)文档导航开始加载,这与始终具有 HR 时间格式的用户计时一起很有用。

我们如何才能在所有情况下获得函数返回 HR 时间?

当我看到一个超过 10 位数字且没有句点的数字时,我知道这是从已弃用的 Navigation Timing 级别 1 获得的时间。所有其他测试用例都给出小数点数字,这意味着它是 HR 时间,精度更高。最大的问题是它们有不同的时间渊源

我经历了混乱、试错和沮丧的搜索(MDN 尚未更新到第 2 级)来确认并声明:

  • 导航计时级别 1 使用unix 纪元时间,其余...
  • 导航计时级别 2 使用HR 时间
  • 用户计时级别 1 使用HR 时间
  • 用户计时级别 2 使用HR 时间
  • 在 Chrome 和 Firefox 中也performance.now()HR 时间。

如何将unix 纪元时间转换为HR 时间


解决了 。:

代码在 Amadan 的帮助下得到纠正。
请参阅接受的答案中的评论。

function nav(eventName, fallback) {
  var lev1 = performance.timing; //deprecated unix epoch time in ms since 1970
  var lev2 = performance.getEntriesByType("navigation")[0]; //ms since page started to load
  var nav = lev2 || lev1; //if lev2 is undefined then use lev1
  if (!nav[eventName] && fallback) eventName = fallback

  // approximate t microseconds it takes to execute performance.now()
  var i = 10000, t = performance.now()
  while(--i) performance.now()
  t = (performance.now() - t)/10000 // < 10 microseconds

  var oldTime = new Date().getTime(), 
      newTime = performance.now(),
      timeOrigin = performance.timeOrigin? 
                   performance.timeOrigin: 
                   oldTime - newTime - t; // approximate

  return nav[eventName] - (lev2? 0: timeOrigin);
  // return nav[eventName] - (lev2? 0: lev1.navigationStart); //alternative?
}

在使用旧的时序lev1performance.timeOrigin情况下会减少。 如果浏览器没有它,则通过减少自 timeOrigin 以来的时间来近似 timeOrigin,从(new Date().getTime())自 Unix Epoch的时间到导致timeOrigin 自 Unix Epoch 的时间。显然这是定义,尽管链接有点模糊。我通过测试确认,我相信答案。希望 w3c 对 timeOrigin 的定义比性能测量开始时间的高分辨率时间戳更好。
performance.now()

函数返回值表示自时间原点以来经过的时间。

在大多数情况下它可能是微不足道的,但它执行的测量时间tperformance.now()删除以近似同时执行。

我在我的 Raspberry Pi 上测量t到几乎 10 微秒,它在各种循环大小下相当稳定。t但是我的联想在测试更大的循环尺寸时没有那么精确地四舍五入并缩短时间。


在最后一行代码中注释掉了另一种解决方案
已弃用performance.timing.navigationStart

表示自 UNIX 纪元以来的时刻(以毫秒为单位),即在卸载提示在同一浏览上下文中的上一个文档上终止之后。如果没有之前的文档,这个值会和 PerformanceTiming.fetchStart 一样

因此,要检查当前文档(忽略任何以前的文档),然后使用已弃用的performance.timing.fetchStart

表示自 UNIX 纪元以来的时刻,以毫秒为单位,浏览器已准备好使用 HTTP 请求获取文档。这个时刻是检查任何应用程序缓存之前。

如果它是浏览器唯一理解的属性,那么使用不推荐使用的属性当然是正确的。当“导航”未定义在getEntriesByType具有良好浏览器支持的情况下使用。


快速检查在此之前通过此行相互确认return

console.log(performance.timeOrigin + '\n' + lev1.navigationStart + '\n' + lev1.fetchStart)

结果在我的 Chrome 中看起来像这样

1560807558225.1611
1560807558225
1560807558241

4

1 回答 1

1

仅当浏览器支持 HR 时间 2 时才有可能:

let unixTime = hrTime + performance.timeOrigin;

let hrTime = unixTime - performance.timeOrigin;

但是,performance通常用于时间差异,它不关心绝对时间戳的来源是什么。

对于不支持 HR time 2 的浏览器,或者半心半意地“支持”它的浏览器,你可以这样伪装:

const hrSyncPoint = performance.now();
const unixSyncPoint = new Date().getTime();
const timeOrigin = unixSyncPoint - hrSyncPoint;

这不是非常精确,但对于大多数用途来说应该足够好(在我的系统上,performance.timeOrigin - timeOrigin是亚毫秒)。

于 2019-06-17T00:41:34.813 回答