2015-09-18 28 views
5

prega, vedere il codice:blocchi DOMContentLoaded di caricamento della pagina

<!-- ... --> 
<head> 
    <style type="text/css"> body { background: gray; } </style> 
</head> 
<body> 
    <p> 
     Firefox does not even shows blank page. 
     Tab is stuck in "suggested sites" for 5 seconds. 
    </p> 
    <p> 
     Chrome show just blank white. No text, no background. For 5 seconds. 
    </p> 
    <p> 
     DOMContentLoaded event handler blocks page 
     loading and rendering. Browser does not start 
     rendering page until DOMContentLoaded 
     handler function return. 
    </p> 

    <script> 
     document.addEventListener('DOMContentLoaded', function() { 
      var timestamp = Date.now() + 5000; while (Date.now() < timestamp); 
      // or synchronous 5 seconds XHR as an equivalent of loop 
     }); 
    </script> 
</body> 
<!-- ... --> 

html statico + css è più che sufficiente a rendere il contenuto (anche se senza IMG, e ma blocca buon di layout non dipende IMG dimensioni). Il layout generale della pagina dovrebbe essere mostrato immediatamente come era sempre stato inteso. E solo dopo il rendering (o almeno iniziando a disegnarlo), Javsacript dovrebbe essere eseguito, indipendentemente dal fatto che controlli solo i collegamenti di clic o il ciclo infinito come nell'esempio qui.

Come è possibile eseguire JS dopo che il layout di pagina statico è effettivamente visualizzato, o almeno ha iniziato ad apparire?

(e "pronto" evento non è adatto qui, perché non è garantito per un incendio in qualsiasi tempo ragionevole)

  • Come si vede dall'esempio non sto usando scrittura documento né ha intenzione di.
  • Inserisco anche la scrittura subito prima del tag di chiusura del corpo
  • Non sto facendo alcun lavoro vero nel tag script - Sottoscrivo l'evento.

Perché il browser impedisce (blocchi) all'utente di visualizzare il contenuto definito staticamente? Almeno i browser moderni possono fermare queste sciocchezze?

UPD. chiarimento

Se si utilizza DOMContentLoaded regolari compiti apparentemente innocui (subsribing agli eventi pulsanti, inizializzazione carico asincrona di altro codice, ecc) è di fatto DO ritardare utente da contenuti che vedono e che è il vero problema con DOMContentLoaded. Il blocco del loop qui è intenzionale, ad esempio, solo per dimostrare che blocca davvero, per coloro che credono erroneamente che DOMContentLoaded sia una cosa sicura "asincrona"/"non bloccante" (che non lo è).

+1

[Perché non usare 'setTimeout'?] (Http://jsfiddle.net/ods26xk1/1) Non è esattamente chiaro che cosa si sta cercando di raggiungere qui. –

+0

@ AndréDion Sì, non completamente chiaro, ma ho capito che il blocco era intenzionale: voleva solo che iniziasse dopo che il contenuto principale è stato visualizzato. – wwwmarty

+0

forse while() è uno stub per una chiamata sincrona ajax ... – wwwmarty

risposta

2

Interessante e inaspettato. Ho risolto con requestAnimationFrame (richiamata), in questo modo:

function foo() { 
    window.requestAnimationFrame(function() { 
     window.requestAnimationFrame(function() { 
      var timestamp = Date.now() + 5000; while (Date.now() < timestamp){}; 
      alert('now'); 
     }); 
    }); 
} 
document.addEventListener('DOMContentLoaded', foo); 
+0

Brillante scoperta, grazie. Quello esattamente come mi aspettavo funzionasse. Questo è strano, che non esiste un altro modo conveniente e standard per una cosa così fondamentale e il problema viene ignorato. –

+1

E ironicamente funziona in FF, ma non in Chrome :) –

+0

Ok, questo è molto fastidioso. A Chrome piace un secondo animationFrame, ma non il primo. Risposta aggiornata .... e sono terrorizzato di provare questo in IE;) – wwwmarty

Problemi correlati