Async Load JavaScript Files with Callback

2019-01-13 22:24发布

I am trying to write an ultra simple solution to load a bunch of JS files asynchronously. I have the following script below so far. However the callback is sometimes called when the scripts aren't actually loaded which causes a variable not found error. If I refresh the page sometimes it just works because I guess the files are coming straight from the cache and thus are there quicker than the callback is called, it's very strange?

var Loader = function () {

}
Loader.prototype = {
    require: function (scripts, callback) {
        this.loadCount      = 0;
        this.totalRequired  = scripts.length;
        this.callback       = callback;

        for (var i = 0; i < scripts.length; i++) {
            this.writeScript(scripts[i]);
        }
    },
    loaded: function (evt) {
        this.loadCount++;

        if (this.loadCount == this.totalRequired && typeof this.callback == 'function') this.callback.call();
    },
    writeScript: function (src) {
        var self = this;
        var s = document.createElement('script');
        s.type = "text/javascript";
        s.async = true;
        s.src = src;
        s.addEventListener('load', function (e) { self.loaded(e); }, false);
        var head = document.getElementsByTagName('head')[0];
        head.appendChild(s);
    }
}

Is there anyway to test that a JS file is completely loaded, without putting something in the actual JS file itself, because I would like to use the same pattern to load libraries out of my control (GMaps etc).

Invoking code, just before the tag.

var l = new Loader();
l.require([
    "ext2.js",
    "ext1.js"], 
    function() {
        var config = new MSW.Config();
        Refraction.Application().run(MSW.ViewMapper, config);
        console.log('All Scripts Loaded');
    });

Thanks for any help.

7条回答
唯我独甜
2楼-- · 2019-01-13 22:34

There is nothing wrong with your code from what I can tell, this is just a bug in Chrome (it does it with window.onload also.)

I'd add it to the function that is triggered in the "load" function. If the variable exists, execute the JS code, but if it doesn't, use a setTimeout to check again in 500ms or so.

查看更多
Juvenile、少年°
3楼-- · 2019-01-13 22:34

Just in case you find this useful, I've created an async utility library that would let you write the above code as:

var Loader = function () {}

Loader.prototype = {
    require: function (scripts, callback) {
        async.map(scripts, this.writeScript, callback);
    },
    writeScript: function(src, callback) {
        var s = document.createElement('script');
        s.type = "text/javascript";
        s.src = src;
        s.addEventListener('load', function (e) { callback(null, e); }, false);
        var head = document.getElementsByTagName('head')[0];
        head.appendChild(s);
    }
}

If you're doing lots of asynchronous calls it has some quite powerful features :)

http://caolanmcmahon.com/async.html

查看更多
霸刀☆藐视天下
4楼-- · 2019-01-13 22:35

What about jQuery....

$.getScript('abc.js'); 

Above code will load the "abc.js" script file asynchronously....

查看更多
倾城 Initia
5楼-- · 2019-01-13 22:54

jcors-loader.js not working in Internet Explorer...

Index.html

<html>
    <head>
    <script type="text/javascript" src="/js/jcors-loader.js"></script>
    <script>
        JcorsLoader.load(
                "js/jquery-1.8.0.js",
                "/js/alertme.js",
                function() {
                    $("#result").text("TEST OK");
                }
        );

    </script>
    </head>
    <body>
    <h1 id="result"></h1>
    </body>
    </html>

alertme.js

alert("Loaded");

This works fine in chrome and firefox it displays "TEST OK" and popup...But no message or alert in IE(7,8,9)...Any help will be appreciated.

查看更多
爷、活的狠高调
6楼-- · 2019-01-13 22:54

Aku menggabungkan scrpit callback dengan tooltip, didalam template blogger. kemudian didalamnya ditambahkan script callbak menggunakan javascipt

Script callback with tooltip

<style>
/* Tooltip container */
.tooltip {
    position: relative;
    display: inline-block;
    text-transform: italic;
    color: blue;
    border-bottom: 1px dotted black;
}


.tooltip .tooltiptext {
    visibility: hidden;
    width: 400px;
    background-color: #fff;
    border: 2px solid #cc6611;
    color: black;
    text-align: left;
	top: 0; left: 6px;
    border-radius: 6px;
	box-shadow: 0 2px 4px -2px #716e6c;
    padding: 15px;
    position: absolute;
    z-index: 999;
    top: 90%;
    left: 10%;
    margin-left: -10px;
}

.tooltip .tooltiptext::after {
    content: "";
    position: absolute;
    bottom: 100%;
    left: 10%;
    margin-left: -10px;
    border-width: 10px;
    border-style: solid;
    border-color: transparent transparent #cc6611 transparent;
}

.tooltip:hover .tooltiptext {
    visibility: visible;
}
</style>

<span class='tooltip'><span class='tooltiptext'><script>
document.write("<script src=\"/feeds/posts/default/-/Your Label Post?max-results="+numposts4+"&orderby=published&alt=json-in-script&callback=showrecentposts4\"><\/script>");
</script>
</span></span>
<!DOCTYPE html>
<html>

<head>
<script type='text/javascript'>
//<![CDATA[

imgr = new Array();
imgr[0] = "http://2.bp.blogspot.com/-uitX7ROPtTU/Tyv-G4NA_uI/AAAAAAAAFBY/NcWLPVnYEnU/s1600/no+image.jpg";
showRandomImg = true;
aBold = true;
summaryPost = 170;
summaryPost4 = 160;
summaryTitle = 100;
numposts = 10;
numposts4 = 5;

function removeHtmlTag(strx,chop){
    var s = strx.split("<");
    for(var i=0;i<s.length;i++){
        if(s[i].indexOf(">")!=-1){
            s[i] = s[i].substring(s[i].indexOf(">")+1,s[i].length);
        }
    }
    s =  s.join("");
    s = s.substring(0,chop-1);
    return s;
}

function showrecentposts(json) {
    j = (showRandomImg) ? Math.floor((imgr.length+1)*Math.random()) : 0;
    img  = new Array();

      for (var i = 0; i < numposts; i++) {
        var entry = json.feed.entry[i];
        var posttitle = entry.title.$t;
        var pcm;
        var posturl;
        if (i == json.feed.entry.length) break;
        for (var k = 0; k < entry.link.length; k++) {
              if (entry.link[k].rel == 'alternate') {
                posturl = entry.link[k].href;
                break;
              }
        }
        
        for (var k = 0; k < entry.link.length; k++) {
              if (entry.link[k].rel == 'replies' && entry.link[k].type == 'text/html') {
                pcm = entry.link[k].title.split(" ")[0];
                break;
              }
        }
        
        if ("content" in entry) {
              var postcontent = entry.content.$t;}
        else
        if ("summary" in entry) {
              var postcontent = entry.summary.$t;}
        else var postcontent = "";
        
        postdate = entry.published.$t;
    
    if(j>imgr.length-1) j=0;
    img[i] = imgr[j];
    
    s = postcontent    ; a = s.indexOf("<img"); b = s.indexOf("src=\"",a); c = s.indexOf("\"",b+5); d = s.substr(b+5,c-b-5);

    if((a!=-1)&&(b!=-1)&&(c!=-1)&&(d!="")) img[i] = d;

    //cmtext = (text != 'no') ? '<i><font color="'+acolor+'">('+pcm+' '+text+')</font></i>' : '';


    var month = [1,2,3,4,5,6,7,8,9,10,11,12];
    var month2 = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];

    var day = postdate.split("-")[2].substring(0,2);
    var m = postdate.split("-")[1];
    var y = postdate.split("-")[0];

    for(var u2=0;u2<month.length;u2++){
        if(parseInt(m)==month[u2]) {
            m = month2[u2] ; break;
        }
    }

    var daystr = day+ ' ' + m + ' ' + y ;
    
    var trtd = '<li style="position:relative;"><div class="imgauto"><a href="'+posturl+'"><img width="200" height="150" class=" " src="'+img[i]+'"/></a></div><h3><a href="'+posturl+'">'+posttitle+'</a><p>'+daystr+' / '+pcm+' comments</p></h3></li>';                    
        document.write(trtd); 
             
              j++;
    }
    
}

function showrecentposts4(json) {
	j = (showRandomImg) ? Math.floor((imgr.length+1)*Math.random()) : 0;
	img  = new Array();
    if (numposts4 <= json.feed.entry.length) {
		maxpost = numposts4;
		}
	else
       {
	   maxpost=json.feed.entry.length;
	   }	
  	for (var i = 0; i < maxpost; i++) {
    	var entry = json.feed.entry[i];
    	var posttitle = entry.title.$t;
		var pcm;
    	var posturl;
    	if (i == json.feed.entry.length) break;
    	for (var k = 0; k < entry.link.length; k++) {
      		if (entry.link[k].rel == 'alternate') {
        		posturl = entry.link[k].href;
        		break;
      		}
    	}
		
		for (var k = 0; k < entry.link.length; k++) {
      		if (entry.link[k].rel == 'replies' && entry.link[k].type == 'text/html') {
        		pcm = entry.link[k].title.split(" ")[0];
        		break;
      		}
    	}
		
    	if ("content" in entry) {
      		var postcontent = entry.content.$t;}
    	else
    	if ("summary" in entry) {
      		var postcontent = entry.summary.$t;}
    	else var postcontent = "";
    	
    	postdate = entry.published.$t;
	
	if(j>imgr.length-1) j=0;
	img[i] = imgr[j];
	
	s = postcontent	; a = s.indexOf("<img"); b = s.indexOf("src=\"",a); c = s.indexOf("\"",b+5); d = s.substr(b+5,c-b-5);

	if((a!=-1)&&(b!=-1)&&(c!=-1)&&(d!="")) img[i] = d;

	//cmtext = (text != 'no') ? '<i><font color="'+acolor+'">('+pcm+' '+text+')</font></i>' : '';


	var month = [1,2,3,4,5,6,7,8,9,10,11,12];
	var month2 = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];

	var day = postdate.split("-")[2].substring(0,2);
	var m = postdate.split("-")[1];
	var y = postdate.split("-")[0];

	for(var u2=0;u2<month.length;u2++){
		if(parseInt(m)==month[u2]) {
			m = month2[u2] ; break;
		}
	}

	var daystr = day+ ' ' + m + ' ' + y ;
    pcm='<a href="'+posturl+'">'+pcm+' comments</a>';
	
 if (i==0) {
	var trtd = '<div class="entry-thumb"><a href="'+posturl+'"><img width="70" height="70" src="'+img[i]+'"/></a></div><h3 class="entry-title"><a href="'+posturl+'">'+posttitle+'</a></h3><div class="entry-meta"></div><div class="entry-excerpt"><p>'+removeHtmlTag(postcontent,summaryPost4)+'...</p></div>';
	document.write(trtd);
}
 if ((i>0)&&(i<maxpost))
    {
	var trtd = '<li class="catlist"><a href="'+posturl+'">'+posttitle+'</a></li>';
	document.write(trtd);
}
	j++;
}

}

 //]]>
</script>
</head>

<body>

And you can see the demo at harga lantai kayu

查看更多
叼着烟拽天下
7楼-- · 2019-01-13 22:56

I recommend you use a tiny loader javascript like JcorsLoader (only 647B with Gzip)

JcorsLoader.load(
                "http://xxxx/jquery.min.js",
                function() {
                    $("#demo").html("jQuery Loaded");
                },
                "http://xxxx/jquery.cookie.js",
                function() {  
                    $.cookie('not_existing'); 
                }
            );

Load multiples js in parallel and execute in order without blocking DOMReady or onload.

https://github.com/pablomoretti/jcors-loader

查看更多
登录 后发表回答