2013-03-08 2 views
7

Ho questa semplice funzione che carica script nel DOM corrente:Caricare uno-script-dopo l'altro

function loadscripts (async) { 
    if(async === undefined) { 
     async = false; 
    } 

    var scripts = []; 
    var _scripts = ['jquery.min.js', 'bootstrap.min.js', 'plugins.js', 'main.js']; 

    for(var s in _scripts) { 
     scripts[s] = document.createElement('script'); 
     scripts[s].type = 'text/javascript'; 
     scripts[s].src = _scripts[s]; 
     scripts[s].async = async; 

     document.getElementsByTagName('head').appendChild(scripts[s]); 
    } 
} 

Sono caricati bene e senza nessun errore. So che ci sono gestori di eventi durante il caricamento degli script di programmazione:

  • onreadystatechange, e
  • onload, ecc

Ora vorrei augurare a effettuare le seguenti operazioni:

  • Carica il primo script dall'array e quando i gestori di eventi completano il carico successivo, e così via (ricorsivamente).

Mi dispiace, non ho fornito i onreadystatechange e onload eventi nella mia funzione.

+0

Ti suggerisco di provare [headjs] (http://headjs.com). È bello gestire diversi script! –

+0

@MiguelRodrigues: grazie per il suggerimento, ma sto creando un proprio script simile alla mia testa :) –

risposta

10

Vorrei farlo in questo modo:

LoadScripts(); 

function LoadScripts(async) 
{ 
    if(async === undefined) { 
     async = false; 
    } 
    var scripts = []; 
    var _scripts = ['jquery.min.js', 'bootstrap.min.js', 'plugins.js', 'main.js']; 

    if(async){ 
     LoadScriptsAsync(_scripts, scripts) 
    }else{ 
     LoadScriptsSync(_scripts,scripts) 
    } 
} 

// what you are looking for : 
function LoadScriptsSync (_scripts, scripts) { 

    var x = 0; 
    var loopArray = function(_scripts, scripts) { 
     // call itself 
     loadScript(_scripts[x], scripts[x], function(){ 
      // set x to next item 
      x++; 
      // any more items in array? 
      if(x < _scripts.length) { 
       loopArray(_scripts, scripts); 
      } 
     }); 
    } 
    loopArray(_scripts, scripts);  
} 

// async load as in your code 
function LoadScriptsAsync (_scripts, scripts){ 
    for(var i = 0;i < _scripts.length;i++) { 
     loadScript(_scripts[i], scripts[i], function(){}); 
    } 
} 

// load script function with callback to handle synchronicity 
function loadScript(src, script, callback){ 

    script = document.createElement('script'); 
    script.onerror = function() { 
     // handling error when loading script 
     alert('Error to handle') 
    } 
    script.onload = function(){ 
     console.log(src + ' loaded ') 
     callback(); 
    } 
    script.src = src; 
    document.getElementsByTagName('head')[0].appendChild(script); 
} 
0

Prova questo:

function loadscripts (async) { 
    if(async === undefined) { 
     async = false; 
    } 

    var scripts = []; 
    var _scripts = ['jquery.min.js', 'bootstrap.min.js', 'plugins.js', 'main.js']; 
    for(var s in _scripts) { 
     scripts[s] = document.createElement('script'); 
     scripts[s].type = 'text/javascript'; 
     scripts[s].src = _scripts[s]; 
     scripts[s].async = async; 
    } 
    var loadNextScript = function() { 
     var script = scripts.shift(); 
     var loaded = false; 
     document.getElementsByTagName('head').appendChild(script); 
     script.onload = script.onreadystatechange = function() { 
      var rs = this.readyState; 
      if (rs && rs != 'complete' && rs != 'loaded') return; 
      if (loaded) return; 
      loaded = true; 
      if (scripts.length) { 
       loadNextScript(); 
      } else { 
       // done 
      } 
     }; 
    }; 
    loadNextScript(); 
} 
+0

non è questa dichiarazione della funzione "loadNextScript" che si suppone essere sotto il "ciclo for"? –

+0

@ZlatanO. No, 'loadNextScript' dovrebbe funzionare" asincronicamente ", mentre' for' viene eseguito in un unico modo di blocco. – Passerby

+0

aha .. da questa soluzione .. aggiunge prima l'oggetto 'scripts', e poi con' loadNextScript() ', li inserisce in un tag' head' - nel documento DOM? –

0

si potrebbe fare con le promesse di questo tipo.

// loads an individual script 
var loadScript = function (path) { 
    // generate promise 
    return new Promise(function (fulfill, reject) { 
     // create object 
     var script = document.createElement('script'); 

     // when it loads or the ready state changes 
     script.onload = script.onreadystatechange = function() { 
      // make sure it's finished, then fullfill the promise 
      if (!this.readyState || this.readyState == 'complete') fulfill(this); 
     }; 

     // begin loading it 
     script.src = path; 

     // add to head 
     document.getElementsByTagName('head')[0].appendChild(script); 
    }); 
}; 

// this is the one you want 
var loadScripts = function (scripts) { 
    return scripts.reduce(function (queue, path) { 
     // once the current item on the queue has loaded, load the next one 
     return queue.then(function() { 
      // individual script 
      return loadScript(path); 
     }); 
    }, Promise.resolve() /* this bit is so queue is always a promise */); 
}; 

Usage:

getScripts(["foo.js", "bar.js"]).then(function() { 
    // whatever you want to happen when it's all done 
}); 

Non fa alcuna gestione degli errori, però, così si dovrà implementare che se ne avete bisogno.

1

Ha dovuto caricare gli script nell'ordine specificato x, y, z e poiché ne avevo solo alcuni. Questo approccio ha funzionato per me. Non è stato possibile caricarli nel corpo o nella testa poiché sono abbastanza grandi e sto utilizzando una pagina di destinazione statica.

document.addEventListener('DOMContentLoaded', function(event) { 
     // initial DOM loaded 
     var vendorJS = document.createElement('script'); 
     vendorJS.src = 'assets/vendor.js'; 

     var appJS = document.createElement('script'); 
     appJS.src = 'assets/application.js'; 

     var envJS = document.createElement('script'); 
     envJS.src = 'assets/env.js'; 

     document.body.appendChild(vendorJS); 

     vendorJS.onload = vendorJS.onreadystatechange = function() { 
      document.body.appendChild(appJS); 

      appJS.onload = appJS.onreadystatechange = function() { 
       document.body.appendChild(envJS); 
      }; 
     }; 
});