Javascript:页面加载完成后运行函数,脚本加载异步

时间:2015-07-09 04:19:08

标签: javascript asynchronous

我无法找到一种可靠的方法来查找页面何时完成加载。我目前的代码如下:

function pageLoaded(callback) {
    function completed() {
        document.removeEventListener('DOMContentLoaded', completed);
        callback();
    }

    if (document.readyState === 'complete') {
        callback();
    } else {
        document.addEventListener('DOMContentLoaded', completed);
    }
}

问题是DOMContentLoadeddocument.readyState设置为'完成'之前被触发,这意味着回调永远不会被调用。

当我的函数运行时DOMContentLoaded已被触发但document.readyState === 'interactive'。但是,我认为由于these possible issues document.readyState === 'interactive' <head> <script src="script.js" async></script> ,我无法运行回调。

不幸的是,由于使用了异步,我不认为我可以制作演示。这也不会100%发生,但似乎总是发生在我重新加载时(我假设与缓存有关)。

请注意,我在我的$result = your database query result; $days = array(); for($i=0;$i<=31;$i++){ { foreach($result as $aresult){ if(($aresult['day']-1)==$i){ $days[i] = $aresult; break; } } }

中加载了我的脚本
OAuthURL = "https://api.instagram.com/oauth/authorize/?client_id=cb0096f08a3848e67355f&redirect_uri=https://www.smashboarddashboard.com/whathappened&response_type=code"
OAuth_AccessRequest = requests.post(OAuthURL)
ResHistory = OAuth_AccessRequest.history
for resp in ResHistory:
    print resp.status_code, resp.url
print OAuth_AccessRequest.status_code, OAuth_AccessRequest.url

2 个答案:

答案 0 :(得分:5)

我无法找到关于这个主题的有用信息,所以我决定做一些测试。我设置了一个节点服务器:

  1. 发送html文档的开头
  2. 等待5秒
  3. 发送包含图片的其余html
  4. 然后我在每个阶段记录了document.readyDOMContentLoaded的状态。我的代码:

    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.readyDOMContentLoaded名称

    没有变化

    子资源完成加载(在本例中为图像)
    Chrome / FF / IE11: document.ready === 'complete'
    IE9 / IE10: document.ready === 'complete'

    正如您所见,IE9&amp; IE10过早设置document.ready === 'interactive'

    一些可能的解决方案

    <强> 1。忽略IE9 / IE10

    if (document.readyState === 'interactive' || document.readyState === 'complete') {
        callback();
    } else {
        document.addEventListener('DOMContentLoaded', callback);
    }
    

    <强> 2。在异步脚本之外的文档DOMContentLoaded中添加<head>。这可确保在调用之前将其附加。

    // 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。在“窗口”上回退到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);
    }
    

答案 1 :(得分:0)

{{1}}