用 JavaScript 计算页面加载时间

我试图做一个网页,当它开始加载,使用间隔开始计时器。

当页面完全加载时,它会停止计时器,

但是99% 的情况下,我得到的时间测量值是0.00或0.01即使这需要更长的时间。

有时候,它会说一些更有意义的东西,比如.28或者3.10。

如果有帮助,下面是代码:

var hundredthstimer = 0;
var secondplace = 0;


function addinc(){


hundredthstimer += 1;
if (inctimer == 100){
hundredthstimer = 0;
secondplace += 1;
}


}


var clockint = setInterval(addinc, 10);


function init(){
var bconv1 = document.getElementById("bconverter1");
var bconv2 = document.getElementById("bconverter2");


$(bconv2).hide();


clearInterval(clockint);


if (inctimer.len !== 2){
inctimer = "0" + inctimer;
}
alert(secondplace + "." + inctimer);
}
onload = init;

所以它基本上创建了一个名为 hundthstimer 的变量,每10毫秒(.01秒)增加1。

然后,如果这个数字达到1000(1整秒) ,那么一个名为 second splace 的变量将上升1,因为这是它运行了整整多少秒。

然后,它警告第二位、小数点和百位作为总加载时间。

但上述错误数字的问题仍然存在。为什么?

151071 次浏览

Don't ever use the setInterval or setTimeout functions for time measuring! They are unreliable, and it is very likely that the JS execution scheduling during a documents parsing and displaying is delayed.

Instead, use the Date object to create a timestamp when you page began loading, and calculate the difference to the time when the page has been fully loaded:

<doctype html>
<html>
<head>
<script type="text/javascript">
var timerStart = Date.now();
</script>
<!-- do all the stuff you need to do -->
</head>
<body>
<!-- put everything you need in here -->


<script type="text/javascript">
$(document).ready(function() {
console.log("Time until DOMready: ", Date.now()-timerStart);
});
$(window).load(function() {
console.log("Time until everything loaded: ", Date.now()-timerStart);
});
</script>
</body>
</html>

Why so complicated? When you can do:

var loadTime = window.performance.timing.domContentLoadedEventEnd- window.performance.timing.navigationStart;

If you need more times check out the window.performance object:

console.log(window.performance);

Will show you the timing object:

connectEnd                 Time when server connection is finished.
connectStart               Time just before server connection begins.
domComplete                Time just before document readiness completes.
domContentLoadedEventEnd   Time after DOMContentLoaded event completes.
domContentLoadedEventStart Time just before DOMContentLoaded starts.
domInteractive             Time just before readiness set to interactive.
domLoading                 Time just before readiness set to loading.
domainLookupEnd            Time after domain name lookup.
domainLookupStart          Time just before domain name lookup.
fetchStart                 Time when the resource starts being fetched.
loadEventEnd               Time when the load event is complete.
loadEventStart             Time just before the load event is fired.
navigationStart            Time after the previous document begins unload.
redirectCount              Number of redirects since the last non-redirect.
redirectEnd                Time after last redirect response ends.
redirectStart              Time of fetch that initiated a redirect.
requestStart               Time just before a server request.
responseEnd                Time after the end of a response or connection.
responseStart              Time just before the start of a response.
timing                     Reference to a performance timing object.
navigation                 Reference to performance navigation object.
performance                Reference to performance object for a window.
type                       Type of the last non-redirect navigation event.
unloadEventEnd             Time after the previous document is unloaded.
unloadEventStart           Time just before the unload event is fired.

Browser Support

More Info

The answer mentioned by @HaNdTriX is a great, but we are not sure if DOM is completely loaded in the below code:

var loadTime = window.performance.timing.domContentLoadedEventEnd- window.performance.timing.navigationStart;

This works perfectly when used with onload as:

window.onload = function () {
var loadTime = window.performance.timing.domContentLoadedEventEnd-window.performance.timing.navigationStart;
console.log('Page load time is '+ loadTime);
}

Edit 1: Added some context to answer

Note: loadTime is in milliseconds, you can divide by 1000 to get seconds as mentioned by @nycynik

It is hard to make a good timing, because the performance.dominteractive is miscalulated (anyway an interesting link for timing developers).

When dom is parsed it still may load and execute deferred scripts. And inline scripts waiting for css (css blocking dom) has to be loaded also until DOMContentloaded. So it is not yet parsed?

And we have readystatechange event where we can look at readyState that unfortunately is missing "dom is parsed" that happens somewhere between "loaded" and "interactive".

Everything becomes problematic when even not the Timing API gives us a time when dom stoped parsing HTML and starting The End process. This standard say the first point has to be that "interactive" fires precisely after dom parsed! Both Chrome and FF has implemented it when document has finished loading sometime after it has parsed. They seem to (mis)interpret the standars as parsing continues beyond deferred scripts executed while people misinterpret DOMContentLoaded as something hapen before defered executing and not after. Anyway...

My recommendation for you is to read about​ Navigation Timing API. Or go the easy way and choose a oneliner of these, or run all three and look in your browsers console ...

  document.addEventListener('readystatechange', function() { console.log("Fiered '" + document.readyState + "' after " + performance.now() + " ms"); });


document.addEventListener('DOMContentLoaded', function() { console.log("Fiered DOMContentLoaded after " + performance.now() + " ms"); }, false);


window.addEventListener('load', function() { console.log("Fiered load after " + performance.now() + " ms"); }, false);

The time is in milliseconds after document started. I have verified with Navigation​ Timing API.

To get seconds for exampe from the time you did var ti = performance.now() you can do parseInt(performance.now() - ti) / 1000

Instead of that kind of performance.now() subtractions the code get little shorter by User Timing API where you set marks in your code and measure between marks.

here's an expression that gives the exact value:

window.performance.timing.loadEventEnd-window.performance.timing.navigationStart