Async Загрузка файлов JavaScript с обратным вызовом
Я пытаюсь написать ультра простое решение для загрузки кучи JS файлов асинхронно. У меня есть следующий ниже script. Однако обратный вызов иногда вызывается, когда сценарии фактически не загружаются, что вызывает ошибку, не найденную переменной. Если я обновляю страницу иногда, это просто работает, потому что я думаю, что файлы идут прямо из кеша и, следовательно, быстрее, чем вызван обратный вызов, это очень странно?
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);
}
}
Есть ли все равно, чтобы проверить, что JS файл полностью загружен, не помещая что-то в собственно файл JS, потому что я хотел бы использовать тот же шаблон для загрузки библиотек из моего контроля (GMaps и т.д.).
Вызов кода, непосредственно перед тегом.
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');
});
Спасибо за любую помощь.
Ответы
Ответ 1
Нет ничего плохого в вашем коде из того, что я могу сказать, это всего лишь ошибка в Chrome (она также работает с window.onload.)
Я бы добавил его к функции, которая запускается в функции "load". Если переменная существует, выполните JS-код, но если это не так, используйте setTimeout для проверки снова через 500 мс или около того.
Ответ 2
Как насчет jQuery....
$.getScript('abc.js');
Выше код будет загружать файл "abc.js" script асинхронно....
Ответ 3
Я рекомендую использовать крошечный javascript загрузчика, такой как JcorsLoader (только 647B с Gzip)
JcorsLoader.load(
"http://xxxx/jquery.min.js",
function() {
$("#demo").html("jQuery Loaded");
},
"http://xxxx/jquery.cookie.js",
function() {
$.cookie('not_existing');
}
);
Загружать кратные js параллельно и выполнять в порядке, не блокируя DOMReady или onload.
https://github.com/pablomoretti/jcors-loader
Ответ 4
На всякий случай, если вы сочтете это полезным, я создал библиотеку утилиты async, которая позволит вам написать приведенный выше код как:
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);
}
}
Если вы выполняете много асинхронных вызовов, у него есть некоторые довольно мощные функции:)
http://caolanmcmahon.com/async.html
Ответ 5
Как и Aaron, там есть ошибка в chrome, но есть проблемы и с IE и другими браузерами.
Я попробовал разные способы создания своего ленивого загрузчика, и у меня было много проблем:
- добавление <script> тег: проблемы с script событиями (onload, onerror и т.д.) в проводнике и других браузерах
- чтение a script с помощью ajax и синтаксический анализ текста (с eval, это javascript, поэтому не беспокойтесь, это не evIl): ОЧЕНЬ сложно отлаживать (он анализируется как одна строка без комментариев, поэтому вы не можете знать, что строка дает вам ошибку)
- чтение script с помощью ajax и добавление <script> тег с текстом script: очень хорошо работает во всех браузерах;
вы можете создавать асинхронные и синхронизирующие загрузки с помощью одной и той же функции, а также управлять очень хорошими ошибками, загрузкой и т.д. (если вы знаете основы ajax, вы должны знать, как обрабатывать переменное состояние HTTP), и это то, что я рекомендую.
Ответ 6
jcors-loader.js не работает в 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
оповещения ( "Loaded" );
Это прекрасно работает в chrome и firefox, на экране отображается "TEST OK" и всплывающее окно... Но в IE нет сообщений или оповещений (7,8,9)... Любая помощь будет оценена.
Ответ 7
Aku menggabungkan scrpit callback dengan tooltip, didalam template blogger.
kemudian didalamnya ditambahkan script callbak menggunakan javascipt
Script обратный вызов с подсказкой
<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>