如何获取未加载的资源?

时间:2017-09-15 13:58:44

标签: javascript

我试图通过在index.html的头部包含一个脚本来获取网页中所有未加载的元素,但我遇到了一些问题。
这是代码:

    document.addEventListener('DOMContentLoaded', function () {
        console.log("here");

        var scripts = document.getElementsByTagName('script');
        for(var i=0;i<scripts.length;i++){
            scripts[i].onerror =function(message, source, lineno) {
                console.log("JS: Error SCRIPT");  
            }
        }


        var imgs = document.getElementsByTagName('img');
        for(var i=0;i<imgs.length;i++){

            imgs[i].onerror =function(message, source, lineno) {
                console.log("JS: Error IMG ");  
            }
        }

        var links = document.getElementsByTagName('link');
        for(var i=0;i<links.length;i++){
            links[i].onerror = function(message, source, lineno){
                console.log("JS: Error CSS ");
            }
        }

    });

我在我调用脚本的HTML文件中放了3个错误的CSS,图像和脚本(它们不作为资源存在)。
当我在本地运行index.html时,我得到“Error IMG”和“Error CSS” 当我在服务器上运行时,我只得到“错误IMG” 在这两种情况下,我都没有得到“Error SCRIPT” 我做错了什么?

更新:这是代码

appmetrics.js

    //class that store page resource data
    /*
    ES6
    class Resource{
        constructor(name,type,start,end,duration){
            this.name = name;
            this.type = type;
            this.start = start;
            this.end = end;
            this.duration = duration;
        }
    }
    */
    function Resource (name,type,start,end,duration){
        this.name = name;
        this.type = type;
        this.start = start;
        this.end = end;
        this.duration = duration;
    }

    /*
    ES6
    class Errors{
        constructor(name,source,line){
            this.name = name;
            this.source = source;
            this.line = line;
        }
    }
    */
    function Errors(name,source,line){
        this.name = name;
        this.source = source;
        this.line = line;
    }

    //endpoint to send data 
    var endpoint = "https://requestb.in/sr8wnnsr"

    var resources = Array();
    var errors = Array();
    var pageLoadTime;

    var start = performance.now();

    window.onload = function(){

        pageLoadTime = performance.now()-start;

        console.log("Page loading time: " + pageLoadTime);

        //getting page resources and pushing them into the array
        var res = performance.getEntriesByType("resource");
        res.forEach(function add(item){
            resources.push(new Resource(item.name,item.initiatorType,item.startTime,item.responseEnd,item.duration));
        })

        console.log(resources);
        var jsonRes = JSON.stringify(resources);
        //sendMetricToEndpoint(jsonRes);
        //sendMetricToEndpoint(pageLoadTime.toString());

    }

    window.onerror = function(message, source, lineno) {
        console.log("Error detected!" + "\nMessage: " +message +"\nSource: "+ source +"\nLine: "+ lineno);    
        errors.push(new Errors(message,source,lineno));
        console.log(errors);
    }

    //Not working code
    /*
            document.addEventListener('DOMContentLoaded', function () {
                console.log("here");

                var scripts = document.getElementsByTagName('script');
                for(var i=0;i<scripts.length;i++){
                    scripts[i].onerror =function(message, source, lineno) {
                        console.log("JS: Errore SCRIPT");  
                    }
                }


                var imgs = document.getElementsByTagName('img');
                for(var i=0;i<imgs.length;i++){

                    imgs[i].onerror =function(message, source, lineno) {
                        console.log("JS: Errore IMG ");  
                    }
                }

                var links = document.getElementsByTagName('link');
                for(var i=0;i<links.length;i++){
                    links[i].onerror = function(message, source, lineno){
                        console.log("JS: Errore CSS ");
                    }
                }

            });

    */

    //StackOverflow solution start

    var scripts = [];

    for (var i = 0, nodes = document.getElementsByTagName('script'); i < nodes.length; i++) {
    scripts[i] = { source: nodes[i].src, loaded: false };
    nodes[i].onload = function() {
        var loadedNode = this;
        var index = scripts.findIndex(function(script) {
        return script.source === loadedNode.src;
        });

        scripts[index].loaded = true;

    };
    }

    var links = [];

    for (var i = 0, nodes = document.getElementsByTagName('link'); i < nodes.length; i++) {

    links[i] = { source: nodes[i].href, loaded: false };

    nodes[i].onload = function() {
        var loadedNode = this;
        var index = links.findIndex(function(link) {
        link.href === loadedNode.href;
        });

        links[index].loaded = true;

    };
    }

    document.addEventListener('DOMContentLoaded', function() {
    console.log("here");
    scripts.filter(function(script) {
        return !script.loaded;
    }).forEach(function(script) {
        console.log("Error loading script: " + script.source);
    });

    links.filter(function(link) {
        return !link.loaded;
    }).forEach(function(link) {
        console.log("Error loading link: " + link.source);
    });

    // and the rest of the elements

    var imgs = document.getElementsByTagName('img');

    for (var i = 0; i < imgs.length; i++) {

        imgs[i].onerror = function() {
        console.log("Error loading image: " + this.src);
        };

    }
    });

    //StackOverflow solution stop

    /**
     * Function that send metric to endpoint.
     * 
     * @param {string} endpoint Where to send data.
     * @param {*} data data to send (JSON or string)
     */
    function sendMetricToEndpoint(data){
        console.log("Sending metrics to endpoint");

        var xhttp;
        xhttp=new XMLHttpRequest();

        xhttp.onreadystatechange = function() {
        if (xhttp.readyState == 4 && xhttp.status == 200) {
            console.log(xhttp.responseText);
        }
        };
        xhttp.open("POST", endpoint, true);
        //xhttp.setRequestHeader("Content-type", "application/json");
        xhttp.send(data);
    }

的index.html

    <html>
    <head>
            <!--<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>-->
            <script src="js/appmetricsmod.js"></script>
            <link rel="stylesheet" href="styletests.css">
            <link rel="stylesheet" href="styletestss.css">
            <link rel="stylesheet" href="styletestsss.css">
            <script src="js/error1.js"></script>
            <script src="js/error2.js"></script>
            <script src="js/error3.js"></script>

    </head>
    <body>

    <img src="imgtest.png"></img>
    <img src="imgErr1.png"></img>
    <img src="imgErr2.png"></img>
    <img src="imgErr3.png"></img>
    <img src="http://images.centrometeoitaliano.it/wp-content/uploads/2016/11/15/l1.jpg"></img>
    <div class="divtest">
        hello this is a test
    </div>


    <script>

    </script>
    </body>
    </html>

2 个答案:

答案 0 :(得分:2)

遗憾的是,您无法通过link事件获得scriptonerror错误加载,但您可以处理已加载的内容,并过滤未加载的内容。这可以通过loadlink标记的script事件来实现。

var scripts = [];

for (var i = 0, nodes = document.getElementsByTagName('script'); i < nodes.length; i++) {

  scripts[i] = { source: nodes[i].src, loaded: false };

  nodes[i].onload = function() {
    var loadedNode = this;
    var index = scripts.findIndex(function(script) {
      return script.source === loadedNode.src;
    });

    scripts[index].loaded = true;

  };
}

var links = [];

for (var i = 0, nodes = document.getElementsByTagName('link'); i < nodes.length; i++) {

  links[i] = { source: nodes[i].href, loaded: false };

  nodes[i].onload = function() {
    var loadedNode = this;
    var index = links.findIndex(function(link) {
      link.href === loadedNode.href;
    });

    links[index].loaded = true;

  };
}

document.addEventListener('DOMContentLoaded', function() {
  console.log("here");

  scripts.filter(function(script) {
    return !script.loaded;
  }).forEach(function(script) {
    console.log("Error loading script: " + script.source);
  });

  links.filter(function(link) {
    return !link.loaded;
  }).forEach(function(link) {
    console.log("Error loading link: " + link.source);
  });

  // and the rest of the elements

  var imgs = document.getElementsByTagName('img');

  for (var i = 0; i < imgs.length; i++) {

    imgs[i].onerror = function() {
      console.log("Error loading image: " + this.src);
    };

  }
});

希望有所帮助:)

答案 1 :(得分:1)

使用上面的资源和错误类,我通过获取页​​面的所有资源然后删除工作资源来解决问题。结果是一组未加载的资源。
这是代码:

     var res = performance.getEntriesByType("resource");
         res.forEach(function add(item){
             resources.push(new Resource(item.name, 
             item.initiatorType,
             item.startTime,
             item.responseEnd,
             item.duration));
         })

var flag = true;
var imgs = document.getElementsByTagName('img');
for(var i=0;i<imgs.length;i++){
    for(var j=0;j<resources.length;j++){
        if(imgs[i].src == resources[j].name){
            flag = false;
        }
    }
    if(flag && imgs[i].src){
        errors.push(new Errors("RES NOT FOUND",imgs[i].src,null));
    }
    flag = true;
}

var scripts = document.getElementsByTagName('script');
for(var i=0;i<scripts.length;i++){
    for(var j=0;j<resources.length;j++){
        if(scripts[i].src == resources[j].name){
            flag = false;
        }
    }
    if(flag && scripts[i].src){
        errors.push(new Errors("RES NOT FOUND",scripts[i].src,null));
    }
    flag = true;
}

var links = document.getElementsByTagName('link');
for(var i=0;i<links.length;i++){
    for(var j=0;j<resources.length;j++){
        if(links[i].src == resources[j].name){
            flag = false;
        }
    }
    if(flag && links[i].href){
        errors.push(new Errors("RES NOT FOUND",links[i].href,null));
    }
    flag = true;
}

console.log(resources);
console.log(errors);