2016-02-19 21 views
6

Si consideri il seguente codice:DOM di carico è bloccato e poi sceneggiatura

<head> 
<style> 
.box{ 
    background-color:red; 
    height:150px;  
    width:150px; 
} 
</style> 
</head> 
<body> 
    <div class="box"></div> 

    <script> 
    var start = new Date(); 
    while(true) { 
    var now = new Date(); 
    if (now-start > 10000) 
    break; 
    } 
    console.log('main thread finished'); 
    </script> 
</body> 

è una grande sorpresa per me che DOM rinvia la propria carico per dieci secondi (.box rettangolo è apparso dopo 10 secondi!) . Dal momento che viene prima (<div class="box"></div>), perché è in attesa dello script che segue? Qualche spiegazione ragionevole?

Grazie

+0

Scusami @ Rayon; tuttavia, dopo le tue modifiche non è evidente che lo script venga dopo DOM! In tal caso, la mia domanda non ha alcun significato ... –

+0

Se si esegue questo snippet, si vedranno gli stessi risultati .. Il posizionamento dello script non fa alcuna differenza in questo caso ... – Rayon

+0

non fa alcuna differenza, sia che tu inserisca il corpo o la testa. L'esecuzione si arresta comunque. –

risposta

1

di semplificare, JavaScript è single-threaded che significa che non può prendersi cura del modello DOM, allo stesso tempo, come prendersi cura del vostro piccolo script. Va uno dopo l'altro.

È possibile trovare un'emulazione completa completa here.

Per evitare il problema dell'interfaccia utente bloccata, potrebbe interessarti conoscere Web Workers.

+1

Se sta andando uno dopo l'altro allora l'elemento dovrebbe essere dipinto prima di eseguire mentre il ciclo ... ha senso? – Rayon

+0

@RayonDabre, beh, volevo dire che non può essere fatto simultaneamente, tuttavia non sono sicuro che inizi esattamente l'elaborazione DOM (forse solo dopo la chiusura '', nessuna idea e non sarei sorpreso se questo fosse specifico del browser) ma ovviamente inizia dopo che il tuo script è stato elaborato. – Anton

+0

@RayonDabre, comunque, per favore vedi la mia risposta aggiornata, puoi usare i web worker per elaborare alcune cose in background. – Anton

0

Questo script non attende il caricamento completo della pagina prima dell'avvio. Quindi è per questo che aspetti 10 secondi. Questo è il motivo per cui tale codice viene solitamente inserito da window.onload o $ (document) .ready().

1

causa del modo in cui il motore funziona (filetto singolo) eventuali blocchi esecuzione di script qualsiasi resa progressiva nella pagina sottostante lo script

enter image description here

+0

Questo non è del tutto corretto. Alcuni browser scaricano altre risorse in parallelo, ma tali risorse non possono essere eseguite o visualizzate fino a quando non viene eseguito questo script. – jfriend00

+0

Dipende da come si configura lo script e la compatibilità del browser. – Sagi

+0

In ogni caso, non ci sono file JS esterni nell'esempio, quindi questa risposta è irrilevante. – Anton

2

"script senza asincrona o differire attributi, nonché come script inline, vengono recuperati ed eseguiti immediatamente, prima che il browser continui a analizzare la pagina. " - da MDN.

Così il tuo script interrompe l'analisi per 10 secondi. Per non parlare del rendering della pagina. Fondamentalmente questo è stato fatto per supportare modifiche html immediate dallo script in esecuzione. Ad esempio, se lo script richiede document.write('More html'), ciò influirà sull'analisi.

A proposito, l'esecuzione dello script ha accesso alla struttura DOM che è stata già analizzata . Considera il seguente esempio.

<div class="box">Affected</div> 
 
<script> 
 
\t [].forEach.call(document.querySelectorAll('.box'), function(box){ 
 
    \t  box.innerText += '... modified'; 
 
    }); 
 
</script> 
 
<div class="box">Not</div>

+0

Ma l'elemento che chiede è prima della sceneggiatura, non dopo. – Qwertiy

0

Secondo al browser standard può rendere questo elemento prima dell'esecuzione dello script. Ma non significa che debba. Ho controllato il tuo codice in 4 browser e solo uno di essi ha disegnato lo .box prima dell'esecuzione dello script - era Opera 12. Tutti gli altri browser - Chrome, FF, IE11 no.

Come ricordo, a volte Chrome ha detto che consente loro di ottimizzare qualcosa, e hanno pensato che la velocità di internet è diventata abbastanza grande da aspettare fino al pieno carico.