2010-06-13 8 views
14

J'essaie d'écrire une solution ultra simple pour charger un tas de fichiers JS de manière asynchrone. J'ai le script suivant ci-dessous jusqu'à présent. Cependant, le rappel est parfois appelé lorsque les scripts ne sont pas chargés, ce qui provoque une erreur non trouvée. Si je rafraichis la page, cela fonctionne parfois parce que je suppose que les fichiers viennent directement du cache et sont donc plus rapides que le callback est appelé, c'est très étrange?Async charger des fichiers JavaScript avec rappel

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); 
    } 
} 

est-il de toute façon de tester qu'un fichier JS est complètement chargé, sans mettre quelque chose dans le fichier JS réel lui-même, parce que je voudrais utiliser le même modèle pour charger les bibliothèques hors de mon contrôle (GMaps etc.) .

Appel du code, juste avant le point.

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'); 
    }); 

Merci pour toute aide.

+0

Dans le navigateur et la version testez-vous cela? –

+0

Dans le dernier WebKit, fait-il dans la dernière version de dev de Chrome :( – Gcoop

+0

Je ne peux pas reproduire cela en utilisant Chromium 5.0.375.70, en chargeant deux scripts d'un CDN et un de localhost (contenant une fonction nécessaire pour exécuter un ligne à l'intérieur de la fonction de rappel.) Mais le drapeau 'async' est-il vraiment nécessaire? Que se passe-t-il si vous commentez' s.async = true; 'out? –

Répondre

2

Il n'y a rien de mal à votre code de ce que je peux dire, cela est juste un bug dans Chrome (il le fait avec window.onload aussi.)

Je l'ajoute à la fonction qui est déclenchée dans la fonction "charger". Si la variable existe, exécutez le code JS, mais si ce n'est pas le cas, utilisez setTimeout pour vérifier à nouveau dans environ 500 ms.

+0

Vous pouvez également tester une fonction présente: par exemple, si vous voulez charger jQuery de cette façon, vous pouvez tester pour la fonction '$' étant présent dans la portée globale: 'if ('$' dans la fenêtre)/* faire quelque chose * /;' –

+0

Merci également ajouté ce chèque :) – Gcoop

2

Juste au cas où vous trouvez cela utile, je l'ai créé une bibliothèque utilitaire async qui vous permettra d'écrire le code ci-dessus:

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); 
    } 
} 

Si vous faites beaucoup de moteurs asynchrones, il appelle a un certain de puissantes fonctionnalités :)

http://caolanmcmahon.com/async.html

4

Qu'en est-jQuery ....

$.getScript('abc.js'); 

Le code ci-dessus chargera le fichier script "abc.js" de façon asynchrone ....

+2

J'utilise le cadre xui déjà et ne veulent pas inclure le cadre jQuery ainsi, il va juste ajouter du poids supplémentaire :) Bien que je ne savais pas que jQuery pouvait le faire, merci! – Gcoop

+0

'getScript' n'a pas de callback qui est appelé une fois le script exécuté. – Flimm

0

Comme Aaron dit qu'il y a un bug dans le chrome, mais il y a aussi des problèmes sur IE et d'autres navigateurs.

I tryed différentes façons de créer mon chargeur paresseux et moi avons eu beaucoup de problèmes:

  • l'ajout d'une balise de script < >: problèmes avec les événements de script (. Onload, onerror, etc) dans l'explorateur et autres lire un script avec ajax et analyser le texte (avec eval, c'est javascript alors ne vous inquiétez pas c'est pas evIl): très difficile à déboguer (il est analysé comme une seule ligne sans commentaires donc vous ne pouvez pas savoir quelle ligne vous donne une erreur)
  • lire le script avec ajax et ajouter un <script> tag avec le texte du script: fonctionne très bien sur tous les navigateurs; vous pouvez créer un chargement asynchrone et synchrone avec la même fonction et vous pouvez également contrôler très bien les erreurs, le chargement, etc. (si vous connaissez les bases d'ajax, vous devez savoir comment gérer l'état http varié) et c'est ce que je recommande.
3

Je vous recommandons d'utiliser un petit chargeur javascript comme JcorsLoader (seulement 647B avec Gzip)

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

multiples charge js en parallèle et exécuter afin sans bloquer domready ou onload.

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

0

jcors-loader.js ne fonctionne pas dans 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

alerte (» Chargé");

Cela fonctionne très bien en chrome et firefox il affiche "TEST OK" et pop-up ... Mais pas de message ou d'alerte dans IE (7,8,9) ... Toute aide sera appréciée.

-1

Aku Menggabungkan rappel de scrp dengan tooltip, modèle de didalam blogger. kemudian didalamnya scénario ditambahkan 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; 
 
\t top: 0; left: 6px; 
 
    border-radius: 6px; 
 
\t 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) { 
 
\t j = (showRandomImg) ? Math.floor((imgr.length+1)*Math.random()) : 0; 
 
\t img = new Array(); 
 
    if (numposts4 <= json.feed.entry.length) { 
 
\t \t maxpost = numposts4; 
 
\t \t } 
 
\t else 
 
     { 
 
\t maxpost=json.feed.entry.length; 
 
\t } \t 
 
    \t for (var i = 0; i < maxpost; i++) { 
 
    \t var entry = json.feed.entry[i]; 
 
    \t var posttitle = entry.title.$t; 
 
\t \t var pcm; 
 
    \t var posturl; 
 
    \t if (i == json.feed.entry.length) break; 
 
    \t for (var k = 0; k < entry.link.length; k++) { 
 
     \t \t if (entry.link[k].rel == 'alternate') { 
 
     \t \t posturl = entry.link[k].href; 
 
     \t \t break; 
 
     \t \t } 
 
    \t } 
 
\t \t 
 
\t \t for (var k = 0; k < entry.link.length; k++) { 
 
     \t \t if (entry.link[k].rel == 'replies' && entry.link[k].type == 'text/html') { 
 
     \t \t pcm = entry.link[k].title.split(" ")[0]; 
 
     \t \t break; 
 
     \t \t } 
 
    \t } 
 
\t \t 
 
    \t if ("content" in entry) { 
 
     \t \t var postcontent = entry.content.$t;} 
 
    \t else 
 
    \t if ("summary" in entry) { 
 
     \t \t var postcontent = entry.summary.$t;} 
 
    \t else var postcontent = ""; 
 
    \t 
 
    \t postdate = entry.published.$t; 
 
\t 
 
\t if(j>imgr.length-1) j=0; 
 
\t img[i] = imgr[j]; 
 
\t 
 
\t s = postcontent \t ; a = s.indexOf("<img"); b = s.indexOf("src=\"",a); c = s.indexOf("\"",b+5); d = s.substr(b+5,c-b-5); 
 

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

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

 

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

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

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

 
\t var daystr = day+ ' ' + m + ' ' + y ; 
 
    pcm='<a href="'+posturl+'">'+pcm+' comments</a>'; 
 
\t 
 
if (i==0) { 
 
\t 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>'; 
 
\t document.write(trtd); 
 
} 
 
if ((i>0)&&(i<maxpost)) 
 
    { 
 
\t var trtd = '<li class="catlist"><a href="'+posturl+'">'+posttitle+'</a></li>'; 
 
\t document.write(trtd); 
 
} 
 
\t j++; 
 
} 
 

 
} 
 

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

 
<body>

Et vous pouvez voir la démonstration à harga lantai kayu

Questions connexes