2009-08-18 16 views
43

C'è un evento che si attiva quando vengono caricati i file JavaScript? Il problema è venuto perché YSlow consiglia di spostare i file JavaScript nella parte inferiore della pagina. Ciò significa che $(document).ready(function1) viene generato prima che venga caricato il file js che contiene il codice per function1.Come rilevare se i file javascript sono caricati?

Come evitare questo tipo di situazione?

risposta

65

non ho un punto di riferimento per questo a portata di mano, ma i tag di script vengono elaborati in ordine, e quindi se si mette il $(document).ready(function1) in un tag script dopo i tag di script che definiscono funzione1, ecc, si dovrebbe essere buona per partire.

<script type='text/javascript' src='...'></script> 
<script type='text/javascript' src='...'></script> 
<script type='text/javascript'> 
$(document).ready(function1); 
</script> 

Naturalmente, un altro approccio sarebbe quello di garantire che si sta utilizzando un solo tag script, in totale, combinando i file come parte del processo di generazione. (A meno che tu non stia caricando gli altri da un CDN da qualche parte). Ciò contribuirà anche a migliorare la velocità percepita della tua pagina.

EDIT: Ho appena realizzato che in realtà non ho risposto alla tua domanda: Non penso che ci sia un evento cross-browser che è stato licenziato, no.C'è, se lavori abbastanza, vedi sotto. È possibile verificare i simboli ed usare setTimeout di riprogrammare:

<script type='text/javascript'> 
function fireWhenReady() { 
    if (typeof function1 != 'undefined') { 
     function1(); 
    } 
    else { 
     setTimeout(fireWhenReady, 100); 
    } 
} 
$(document).ready(fireWhenReady); 
</script> 

... ma non si deve avere a che fare che se si ottiene il vostro ordine tag script corretto.


Aggiornamento: È possibile ottenere le notifiche di carico per script elementi aggiunti alla pagina in modo dinamico, se volete. Per ottenere un ampio sostegno del browser, devi fare due cose diverse, ma come una tecnica combinata funziona:

function loadScript(path, callback) { 

    var done = false; 
    var scr = document.createElement('script'); 

    scr.onload = handleLoad; 
    scr.onreadystatechange = handleReadyStateChange; 
    scr.onerror = handleError; 
    scr.src = path; 
    document.body.appendChild(scr); 

    function handleLoad() { 
     if (!done) { 
      done = true; 
      callback(path, "ok"); 
     } 
    } 

    function handleReadyStateChange() { 
     var state; 

     if (!done) { 
      state = scr.readyState; 
      if (state === "complete") { 
       handleLoad(); 
      } 
     } 
    } 
    function handleError() { 
     if (!done) { 
      done = true; 
      callback(path, "error"); 
     } 
    } 
} 

Nella mia esperienza, notifica di errore (onerror) non è al 100% cross-browser affidabile. Si noti inoltre che alcuni browser eseguiranno entrambi i meccanismi, quindi la variabile done per evitare le notifiche duplicate.

+0

Grazie per la risposta, ma per me sembra in qualche modo strano perché dovrei inserire $ (document) .ready (...) dopo il tag

0

Modificare l'ordine di caricamento degli script in modo che function1 sia stato definito prima di utilizzarlo nella richiamata ready.

Inoltre ho sempre trovato meglio definire ready callback come un metodo anonimo poi nominato uno.

+0

Beh, non è possibile definirlo prima perché è in file javascript. –

+0

È possibile includere prima il file con la definizione 'function1' e quindi includere un altro file che utilizza quella funzione. Il punto è che non puoi semplicemente aggiungere file di script in ordine casuale. – RaYell

5

Quando dicono "La parte inferiore della pagina" essi non significano letteralmente il fondo: significano poco prima della chiusura </body> tag. Inserisci i tuoi script lì e saranno caricati prima dell'evento DOMReady; posizionali in seguito e il DOM sarà pronto prima di essere caricato (perché è completo quando viene analizzato il tag di chiusura </html>), che come hai trovato non funzionerà.

Se vi state chiedendo come io so che questo è il loro significato: ho lavorato a Yahoo! e abbiamo messo i nostri script appena prima del tag </body> :-)

EDIT: anche, vedi T.J. La risposta di Crowder e assicurati di avere le cose nell'ordine corretto.

1

Ho sempre effettuato una chiamata dalla fine dei file JavaScript per registrarne il caricamento e ha funzionato perfettamente per me per tutti i browser.

Es: Ho un index.htm, Js1.js e Js2.js. Aggiungo la funzione IAmReady (Id) nell'intestazione index.htm e la chiamo con i parametri 1 e 2 dalla fine dei file, rispettivamente Js1 e Js2. La funzione IAmReady avrà una logica per eseguire il codice di avvio quando riceve due chiamate (memorizzando il numero di chiamate in una variabile statica/globale) dai due file js.

1

A seguito @ T.J. risposta Crowder s', ho aggiunto un ciclo esterno ricorsivo che permette di scorrere tutti gli script in un array e poi eseguire una funzione una volta che tutti gli script sono stati caricati:

loadList([array of scripts], 0, function(){// do your post-scriptload stuff}) 

function loadList(list, i, callback) 
{ 
    { 
     loadScript(list[i], function() 
     { 
      if(i < list.length-1) 
      { 
       loadList(list, i+1, callback); 
      } 
      else 
      { 
       callback(); 
      } 
     }) 
    } 
} 

Naturalmente è possibile effettuare una wrapper per sbarazzarsi dello "0", se lo desideri:

function prettyLoadList(list, callback) 
{ 
    loadList(list, 0, callback); 
} 

Nice work @TJ Crowder - Avevo paura di 'aggiungere solo un paio di secondi di ritardo prima di eseguire la richiamata' che ho visto in altri thread.

Problemi correlati