Javascript:当页面加载完成时运行函数,脚本正在异步加载
Javascript: Run function when page has finished loading, script is loading async
我找不到可靠的方法来查找页面何时加载完成。我当前的代码如下:
function pageLoaded(callback) {
function completed() {
document.removeEventListener('DOMContentLoaded', completed);
callback();
}
if (document.readyState === 'complete') {
callback();
} else {
document.addEventListener('DOMContentLoaded', completed);
}
}
问题是DOMContentLoaded
在document.readyState
设置为"complete"之前被激发,这意味着永远不会调用回调。
当我的函数运行时,DOMContentLoaded
已经被激发,但document.readyState === 'interactive'
。然而,由于这些可能的问题,我认为我不能在document.readyState === 'interactive'
时运行回调。
不幸的是,由于使用了异步,我认为我无法制作演示。此外,这种情况并非100%发生,但似乎总是在我进行硬重新加载时发生(我认为这与缓存有关(。
注意,我在<head>
:中像这样加载脚本
<script src="script.js" async></script>
我找不到太多关于这个主题的有用信息,所以我决定做一些测试。我设置了一个节点服务器,它将:
- 发送html文档的开头
- 等待5秒
- 发送包含图像的html的其余部分
然后我记录了document.ready
和DOMContentLoaded
在每个阶段的状态。我的代码:
var http = require('http');
var server = http.createServer(function(req, res) {
// Send the first part of the html
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(
'<!doctype html>' +
'<html lang="en">' +
'<head>' +
'<meta charset="utf-8">' +
'<meta http-equiv="x-ua-compatible" content="ie=edge">' +
'<title>JS Ready Test</title>' +
'<meta name="description" content="">' +
'<meta name="viewport" content="width=device-width, initial-scale=1">' +
'<script>' +
'console.log(document.readyState);' +
'document.onreadystatechange = function () {' +
'console.log(document.readyState);' +
'};' +
'document.addEventListener("DOMContentLoaded", function() {' +
'console.log("DOMContentLoaded");' +
'});' +
'</script>' +
'</head>' +
'<body>');
// Send a bunch of blank spaces so that the browser will load the buffer, if the buffer is too small the browser will wait for more data
var str = 'Start';
for (var i = 0; i < 2000; i++){
str += ' ';
}
res.write(str);
// Wait 5 seconds and send the rest of the data
setTimeout(function () {
res.write('Finish<img src="https://upload.wikimedia.org/wikipedia/commons/3/3d/LARGE_elevation.jpg"></body></html>');
res.end();
}, 5000);
});
// Listen on port 3000
server.listen(3000);
我的测试结果
第一缓冲区
Chrome(v43(/FF(v39(/IE11:document.ready === 'loading'
IE9/IE10:document.ready === 'interactive'
最终缓冲区
Chrome/FF/IE11:document.ready === 'interactive'
,DOMContentLoaded
调用
IE9/IE10:document.ready
、DOMContentLoaded
无变化,称为
子资源完成加载(在本例中为图像(
铬/FF/IE11:document.ready === 'complete'
IE9/IE10:document.ready === 'complete'
正如你所看到的IE9&IE10过早设置document.ready === 'interactive'
。
一些可能的解决方案
1.忽略IE9/IE10
if (document.readyState === 'interactive' || document.readyState === 'complete') {
callback();
} else {
document.addEventListener('DOMContentLoaded', callback);
}
2.在异步脚本之外的文档的<head>
中添加DOMContentLoaded
。这样可以确保在调用之前先附加它
// In <head>
<script>
var pageLoaded = false;
document.addEventListener('DOMContentLoaded', function() {
pageLoaded = true;
});
</script>
// In script.js
if (pageLoaded) {
callback();
} else {
document.addEventListener('DOMContentLoaded', callback);
}
3.回退到`window上的load
事件
if (document.readyState === 'complete') {
callback();
} else {
// You would need to add a safety so that your functions don't get called twice
document.addEventListener('DOMContentLoaded', callback);
window.addEventListener( "load", callback);
}
function pageLoad(callback) {
if ("function" == typeof callback) {
if (document.addEventListener) { // Event that fires when the initial HTML document has been completely loaded and parsed
document.addEventListener("DOMContentLoaded", callback, false);
} else if (window.attachEvent) { // For IE 8 and below
window.attachEvent("onload", callback);
} else if ("function" == typeof window.onload) { // Event that fires when the page has fully loaded including images / scripts etc
var o = window.onload;
window.onload = function() {
o();
callback();
};
} else {
window.onload = callback;
}
}
}
- Google Adsense多次加载脚本
- 如何准确执行加载脚本&退出弹出窗口
- RequireJ无法随机加载脚本
- 通过浏览器加载页面时触发加载脚本(js或jQuery)'s”;返回“;作用
- 在以前的文件夹中加载脚本
- 如何重新加载脚本标记
- 正在脚本中加载脚本
- 在pjax完成其工作时加载脚本
- I'我用setTimeout加载脚本,你能找到一个更快的方法吗
- 在页面模板上加载脚本
- 如何在我的情况下创建加载脚本
- 当用$.getScript()加载脚本时,有一种方法可以从用$.get script()装载的脚本中调用父脚本中的函数
- 延迟加载 脚本加载和/或执行
- 如何使用谷歌页面速度CSS加载脚本延迟多个CSS文件
- 最后加载脚本
- 如何基于HTML中的类加载脚本
- 在局部视图中加载脚本文件
- 如何防止在使用hapi.js reply().hold()时重新加载脚本
- 异步加载脚本
- 脚本加载脚本广告