2010-11-22 4 views
0

J'ai la liste javascript suivante, chaque élément de cette liste a un fichier script url et une fonction de rappel, ce que je veux faire est de parcourir cette liste, charger chaque script, puis exécuter la fonction de rappel, et PAS passer à l'élément suivant à moins que le rappel en cours est fait exécuter ..Chargement de fichiers javascript automatiquement avec des rappels séquentiels


var data = { 
    scripts: [ 
     { 
      file : 'some-script.js', 
      callback: function() { 
       // do some code here 
      }, 
     }, 
     { 
      file : 'another-script.js', 
      callback: function() { 
       // do some code here 
      }, 
     }, 
     ... 
    ] 
}; 

comment puis-je faire cela automatiquement, si possible?

+1

** Hors-sujet **: Les virgules ballants après la dernière propriété dans votre littéraux d'objet vont être un problème pour vous dans certains navigateurs, les détails: http://blog.niftysnippets.org/2010 /09/literal-improvement.html –

+0

J'ai placé cette virgule pour indiquer qu'il y aura plus que ces scripts à charger, de toute façon je vous remercie pour votre commentaire, aussi pour le poste, mais je ne pense pas que placer le temps d'attente est un bon idée, comme je prévois de faire quelque chose qui fonctionne universellement, peu importe le code de rappel qu'il contient .. –

Répondre

2

(Je suppose que vous utilisez JSONP pour charger vos scripts externes) Le problème que vous rencontrerez est que ces scripts ne chargeront pas tous en même temps. Ci-dessous un code qui appellera votre fonction de rappel dès que le script associé est chargé.

function include_js(url, callback) { // http://www.nczonline.net 
     var script = document.createElement("script"); 
     script.type = "text/javascript"; 

     if (script.readyState) { //IE 
      script.onreadystatechange = function(){ 
       if (script.readyState == "loaded" || script.readyState == "complete"){ 
        script.onreadystatechange = null; 
        callback(); 
       } 
      }; 
     } else { //Others 
      script.onload = function(){ 
       callback(); 
      }; 
     } 
     script.src = url; 
     document.getElementsByTagName("head")[0].appendChild(script); 
    } 

//Edit 

    for (var i = 0; i < data.scripts.length; i++) { 
     include_js(data.scripts[i].file, data.scripts[i].callback); 
    } 
+0

a fonctionné parfaitement! –

+0

ce que j'ai compris ici, dans votre boucle for, il ne va pas à l'élément suivant dans la liste jusqu'à ce que la fonction anonyme termine l'exécution de son code?, Est-ce exact? –

1

Il est possible de si le symbole est un symbole que vous pouvez tester dans chaque script ou si chaque script peut exécuter un appel de fonction une fois le chargement terminé.

Chargement du script est facile, comme je suis sûr que vous savez: (. Vous verrez des gens à annexant head au lieu, n'a pas d'importance, et body est facile à trouver)

var script = document.createElement('script'); 
script.src = /* ... the source path ... */; 
document.body.appendChild(script); 

Mais le plus difficile est de savoir quand il a été téléchargé et exécuté. Les seules façons de le faire sont d'interroger pour voir si un nouveau symbole global défini par le script a été défini, ou en demandant au script de vous rappeler activement quand le chargement est terminé (a'la JSONP). De toute façon, une fois que vous avez détecté le symbole ou obtenu le rappel, vous passez au chargement du script suivant.

Voici un croquis rapide et sale de le faire sur la base de la recherche d'un symbole mondial (une propriété sur l'objet window):

// The scripts to load 
var scriptList = { 
    scripts: [ 
     { 
      file : 'some-script.js', 
      callback: function() { 
       // do some code here 
      }, 
      symbol : "someSymbol", 
      timeout : 30000 // We know this one is slow, give it 30 seconds 
     }, 
     { 
      file : 'another-script.js', 
      callback: function() { 
       // do some code here 
      }, 
      symbol : "anotherSymbol" 
     }, 
     // ... 
    ] 
}; 

// Triggering the load 
loadScripts(scriptList); 

// Library routines to do the load 
function loadScripts(list) 
{ 
    var index, timeout; 

    // Start with the first one (loadNextScript starts with an increment) 
    index = -1; 
    loadNextScript(); 

    // This function loads the next script in the list; if there are no 
    // more, it simply returns 
    function loadNextScript() 
    { 
     var script; 

     // Are there more? 
     ++index; 
     if (index < list.length) 
     { 
      // Yes, append a `script` element 
      script = document.createElement('script'); 
      script.src = list.file; 
      document.body.appendChild(script); 

      // Determine when to time out 
      timeout = new Date() + (list[index].timeout || 20000); // Time out in Xms, default 20 seconds 

      // Start polling 
      setTimeout(pollForScript, 0); // Async, but almost immediately (4-10ms on most browsers) 
     } 
    } 

    // This function polls to see if the current script has loaded yet by 
    // checking for a global symbol it defines. 
    function pollForScript() 
    { 
     var result; 

     // Has it been too long? 
     if (new Date() > timeout) 
     { 
      // Yes 
      result = "timeout"; 
     } 
     else 
     { 
      // Has the symbol been defined? 
      if (typeof window[list[index].symbol] !== "undefined") 
      { 
       // Yes 
       result = "loaded"; 
      } 
      else 
      { 
       // Nope, keep waiting 
       setTimeout(pollForScript, 250); // Check every quarter-second 
      } 
     } 

     // Did we get a result? 
     if (result) 
     { 
      // Yes, do the callback telling it of the result 
      try { 
       list[index].callback(result); 
      } 
      catch (e) { 
      } 

      // Load the next script 
      loadNextScript(); 
     } 
    } 
} 
0

Laissez le rappel appeler votre loadTheNextScriptInList ou quelle que soit la fonction. Vous pouvez le faire automatiquement en ajoutant une fonction anonyme à l'événement onLoad. Cette fonction anonyme doit d'abord appeler le rappel défini dans la liste, puis appeler votre fonction loadTheNextScriptInList.

0

c'est juste quelque chose de rapide que j'ai écrit et testé, mais il devrait faire ce que vous cherchez d'une manière récursive. Espérons que cela aide:

var data = { 
    scripts: [ 
     { 
      file : 'some-script.js', 
      callback: function() { 
       // do some code here 
      }, 
     }, 
     { 
      file : 'another-script.js', 
      callback: function() { 
       // do some code here 
      }, 
     }, 
     ... 
    ] 
}; 


$(document).ready(function() { 

    if(data.scripts.length > 0) { 
     scriptLoader(0); 
    } 

}); 

function scriptLoader(i) { 


    var currScript = data.scripts[i]; 


    $.getScript(currScript.file, function() { 

     // execute your callback 
     currScript.callback(); 

     // load next script 
     if(i < data.scripts.length) { 
     scriptLoader(i++); 
     } 

    }); 

} 

Oh et btw celui-ci utilise le framework javascript JQuery, juste FYI.

+0

Juste pensé que je mentionnerais que ce n'était pas beaucoup d'utilisation dans ma tentative de charger dynamiquement jquery et ses fichiers dépendants séquentiellement. Cela semble simple sinon.: P – purefusion

Questions connexes