浏览器事件的timeStamp来自Javascript在哪里?

时间:2015-05-14 07:54:55

标签: javascript event-handling timing

传递给事件处理程序回调的事件对象包含事件发生时的event.timeStamp,但生成的时间戳在哪里?它是从底层操作系统中冒出来的,还是由浏览器生成的?

我对计算时间戳的可靠性感兴趣,并认识到产生时间戳的时间越晚,它可能就越不准确。

此外,平台和浏览器实现之间产生时间戳的方式有很大差异吗?

感谢。

1 个答案:

答案 0 :(得分:2)

根据DOM4 specification §4.2,在创建事件时分配了它(您必须向下滚动一下):

  

timeStamp属性必须返回初始化的值。创建事件时,必须将属性初始化为自1970年1月1日00:00:00 UTC以来经过的毫秒数,忽略闰秒。

这导致了以下问题:事件何时创建?我可以想到它可以做三次:

  1. 操作系统通知浏览器时

  2. 当JavaScript主要UI线程接下来能够做任何事情时

  3. 当JavaScript主UI线程即将调度与事件相关的任务时

  4. 使用下面的代码段,至少对于click事件,它似乎因浏览器而异:

    • 当JavaScript主要UI线程准备处理事件时,Chrome似乎会分配timeStamp(上面的#3);事件实际发生之后,这可能是显着的,即使主要的JavaScript UI线程有机会在过渡期间做其他事情。 (对我来说,这非常令人惊讶。)

    • Firefox似乎在事件发生时分配timeStamp(上面的#1),无论主要的JavaScript UI线程在做什么。这就是我所期望的。

    • IE 似乎来做Chrome所做的事情(#3),但我不能排除第二次点击时为第三次点击分配时间戳的可能性已处理(#2),因为当事情繁忙时,我无法识别第三个按钮上的点击。

    
    
    // Sadly, Firefox has a bug (https://bugzilla.mozilla.org/show_bug.cgi?id=77992) where
    // timeStamp is not from The Epoch, it's from system start. So we work relative to the
    // moment you clicked the first button rather than working with nice clean absolute data.
    
    // Sadly, IE11 doesn't like you clicking the second button and then moving over to
    // click the third, but the data from just clicking the second suggests it's more like
    // Chrome than Firefox.
    var start1;
    var start2;
    document.getElementById("start").addEventListener("click", function(e) {
      // Remember this event's timestamp
      start1 = e.timeStamp;
      start2 = 0;
    
      // Start a busy-loop for three seconds, locking up the main JS thread
      busy(3000);
      display("Done with first busy loop");
    }, false);
    
    document.getElementById("then1").addEventListener("click", function(e) {
      // Show time since first event
      showElapsed(e.timeStamp);
    
      // Remember this event's timetsamp
      start2 = e.timeStamp;
    
      // Another busy-loop, just a second this time
      busy(1000);
      display("Done with second busy loop");
    }, false);
    
    document.getElementById("then2").addEventListener("click", function(e) {
      // Show time since first and second events
      showElapsed(e.timeStamp);
    }, false);
    
    function showElapsed(ts) {
      display("Elapsed from first event: " + (ts - start1) + "ms");
      if (start2) {
        display("Elapsed from second event: " + (ts - start2) + "ms");
      }
    }
    
    function busy(duration) {
      var target = Date.now() + duration;
      while (Date.now () < target) {
        // Wait
      }
    }
    
    function display(msg) {
      var p = document.createElement('p');
      p.innerHTML = msg;
      document.body.appendChild(p);
    }
    function format(ts) {
      return new Date(ts).toISOString().substring(11, 23);
    }
    &#13;
    <input type="button" id="start" value="Click me">
    <input type="button" id="then1" value="Then me quickly afterward">
    <input type="button" id="then2" value="Then me quickly after that (not on IE!)">
    &#13;
    &#13;
    &#13;