Dokument JavaScript.napisz Inline script Execution Order

Mam następujący skrypt, gdzie pierwszy i trzeci {[1] } są statyczne, a drugi jest generowany :

<script language="javascript" type="text/javascript">
document.write("<script language='javascript' type='text/javascript' src='before.js'><\/sc" + "ript>");
document.write("<script language='javascript' type='text/javascript'>alert('during');<\/sc" + "ript>");
document.write("<script language='javascript' type='text/javascript' src='after.js'><\/sc" + "ript>");
</script>

Firefox i Chrome wyświetli przed, podczas i po, podczas gdy Internet Explorer pokazuje najpierw podczas, a dopiero potem pokazuje przed i po .

Natknąłem się na artykuł, który stwierdza że nie jestem pierwszym, który się z tym zetknął, ale to prawie nie sprawia, że czuję się jak jakiś lepiej.

Czy ktoś wie jak Mogę ustawić kolejność deterministyczną we wszystkich przeglądarkach, albo zhakować IE tak, aby działał jak wszystkie inne, rozsądne przeglądarki?

Zastrzeżenia: fragment kodu jest bardzo prostym repro. Jest on generowany na serwerze i drugi skrypt jest jedyną rzeczą, która się zmienia. Jest to długi skrypt, a powodem są dwa skrypty przed i po nim, dzięki czemu przeglądarka będzie je buforować, a dynamiczna część kodu będzie tak mała, jak to możliwe. Może również pojawiać się wiele razy na tej samej stronie z innym wygenerowanym kodem.

Author: Dustman, 2008-09-18

7 answers

Nie, to jest zachowanie Internet Explorera.

Jeśli dołączasz Skrypty dynamicznie, IE, Firefox i Chrome będą pobierać skrypty w sposób asynchroniczny.

Firefox i Chrome poczekają, aż wszystkie żądania asynchroniczne powrócą, a następnie wykonają skrypty w kolejności, w jakiej są dołączone do DOM, ale IE wykonuje skrypty w kolejności, w jakiej są zwracane przez przewód.

Ponieważ alert zajmuje mniej czasu na "odzyskanie" niż zewnętrzny plik javascript, który prawdopodobnie wyjaśnia zachowanie, które widzisz.

Z postu Kristoffera Henrikssona na temat asynchronicznego ładowania skryptu :

W tym scenariuszu IE i Firefox będą Pobierz oba Skrypty, ale Internet Explorer wykona je również w zamów Zakończ pobieranie w natomiast Firefox pobiera je asynchronicznie, ale nadal wykonuje je w kolejności, w jakiej są dołączone w DOM.

W Internecie Explorer oznacza to, że Twój skrypty nie mogą zależeć od siebie jako nakaz egzekucji będzie się różnić w zależności od sieci korki, pamięci podręczne itp.

Rozważ użycie loadera Javascript. Pozwoli Ci określić zależności skryptów i kolejność wykonywania, a także ładować Skrypty asynchronicznie pod kątem szybkości, a także wygładzić niektóre różnice w przeglądarce.

To jest całkiem dobry przegląd kilku z nich: Essential JavaScript: the top five script loaders .

Używałem zarówno RequireJS jak i LabJS. Moim zdaniem LabJS jest trochę mniej opiniotwórczy.

 24
Author: Timothy Lee Russell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-20 02:39:12

Znalazłem odpowiedź bardziej do moich upodobań:

<script language="javascript" type="text/javascript">
document.write("<script language='javascript' type='text/javascript' src='before.js'><\/sc" + "ript>");
document.write("<script defer language='javascript' type='text/javascript'>alert('during');<\/sc" + "ript>");
document.write("<script defer language='javascript' type='text/javascript' src='after.js'><\/sc" + "ript>");
</script>

Spowoduje to odroczenie ładowania zarówno podczas , jak i Po do momentu zakończenia ładowania strony.

Myślę, że to najlepsze, co mogę dostać. Mam nadzieję, że ktoś będzie w stanie dać lepszą odpowiedź.
 5
Author: Omer van Kloeten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-23 10:04:13

Slajdy 25/26 z ta prezentacja mówi o cechach różnych metod wstawiania skryptów. Sugeruje to, że IE jest jedyną przeglądarką, która będzie wykonywać te skrypty w kolejności. Wszystkie inne przeglądarki wykonają je w kolejności, w której zakończą Ładowanie. Nawet IE nie uruchomi ich w kolejności, jeśli jeden lub więcej ma wbudowane js zamiast src.

Jedną z proponowanych metod jest wstawienie nowego elementu DOM:

var se1 = document.createElement('script');
se1.src = 'a.js';

var se2 = document.createElement('script');
se2.src = 'b.js';

var se3 = document.createElement('script');
se3.src = 'c.js';

var head = document.getElementsByTagName('head')[0]
head.appendChild(se1);
head.appendChild(se2);
head.appendChild(se3);

Aby zrobić drugą sekcję skryptu wygenerowany możesz użyć skryptu do wygenerowania tej treści i przekazać parametry:

se2.src = 'generateScript.php?params=' + someParam;

EDIT: pomimo tego, co napisał artykuł, moje testy sugerują, że większość przeglądarek uruchomi twój dokument.pisz skrypty w kolejności, jeśli każdy z nich ma src, więc chociaż myślę, że metoda powyżej jest preferowana, możesz to zrobić również:

<script language="javascript" type="text/javascript">
document.write("<script type='text/javascript' src='before.js'><\/sc" + "ript>");
document.write("<script type='text/javascript' src='during.php?params=" + params + "'><\/sc" + "ript>");
document.write("<script type='text/javascript' src='after.js'><\/sc" + "ript>");
</script>

Edytuj ponownie (odpowiedź na komentarze do siebie i innych): już generujesz skrypt na swojej stronie. Cokolwiek robisz może być przeniesiony na inny skrypt po stronie serwera, który generuje ten sam blok kodu. Jeśli potrzebujesz parametrów na swojej stronie, przekaż je do skryptu w ciągu zapytania.

Możesz również użyć tej samej metody, jeśli, jak sugerujesz, generujesz skrypt inline wiele razy:

<script language="javascript" type="text/javascript">
document.write("<script type='text/javascript' src='before.js'><\/sc" + "ript>");
document.write("<script type='text/javascript' src='during.php?params=" + params1 + "'><\/sc" + "ript>");
document.write("<script type='text/javascript' src='during.php?params=" + params2 + "'><\/sc" + "ript>");
document.write("<script type='text/javascript' src='during.php?params=" + params3 + "'><\/sc" + "ript>");
document.write("<script type='text/javascript' src='after.js'><\/sc" + "ript>");
</script>

Jednak zaczyna to wyglądać tak, jakbyś podchodził do tego w złą stronę. Jeśli generujesz duży blok kodu wiele razy, prawdopodobnie powinieneś zastąpić go pojedynczym funkcja js i wywołanie go z różnych params zamiast...

 1
Author: Prestaul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-18 17:36:54

Ok...podczas...

// During.js
during[fish]();
Po...
// After.js
alert("After");
fish++

HTML

<!-- some html -->
<script language="javascript" type="text/javascript">
document.write("<script language='javascript' type='text/javascript' src='before.js'></sc" + "ript>");
document.write("<script language='javascript' type='text/javascript'>during[" + fish + "] = function(){alert('During!' + fish);}</sc" + "ript>");
document.write("<script language='javascript' type='text/javascript' src='during.js'></sc" + "ript>");
document.write("<script language='javascript' type='text/javascript' src='after.js'></sc" + "ript>");
</script>
<!-- some other html -->
<script language="javascript" type="text/javascript">
document.write("<script language='javascript' type='text/javascript' src='before.js'></sc" + "ript>");
document.write("<script language='javascript' type='text/javascript'>during[" + fish + "] = function(){alert('During!' + fish);}</sc" + "ript>");
document.write("<script language='javascript' type='text/javascript' src='during.js'></sc" + "ript>");
document.write("<script language='javascript' type='text/javascript' src='after.js'></sc" + "ript>");
</script>
Jestem skłonny zgodzić się co do tego, jak to zaczyna pachnieć. W szczególności, dlaczego nie można kodować "Podczas" do dynamicznie tworzonego pliku js, i wstawić to?

Zauważ, że dynamicznie generowany skrypt trafia do funkcji w drugim dokumencie.pisz.
Testowane w FF2, IE7

 1
Author: Dustman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-18 19:06:19

Możesz wymusić wykonanie secuential przez zdefiniowanie zdarzeń" onload " (lub podobnych) w skryptach i wstrzyknięcie następnego w funkcji event. To nie jest trywialne, ale jest wiele przykładów, tutaj jest jeden.

Http://www.phpied.com/javascript-include-ready-onload/

Myślę, że popularne biblioteki jak jQuery lub prototype mogą w tym pomóc.

 1
Author: Victor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-19 11:03:49

Kod do podania:

<script language="javascript" type="text/javascript">
document.write("<script language='javascript' type='text/javascript'>function callGeneratedContent() { alert('during'); }<\x2Fscript>");
document.write("<script language='javascript' type='text/javascript' src='before.js'><\x2Fscript>");
document.write("<script language='javascript' type='text/javascript' src='after.js'><\x2Fscript>");
</script>

W przed.js:

alert("Before");
callGeneratedContent();

Po.js:

alert("After");

Musisz najpierw wstawić wygenerowaną linię, w przeciwnym razie FF będzie narzekał, ponieważ wykonuje wcześniej.js przed zobaczeniem definicji funkcji.

 0
Author: PhiLho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-19 09:06:14

Co ty na to:

<script>
document.write("<script src='before.js'><\/script>");
</script>

<script >
document.write("<script>alert('during');<\/script>");
</script>

<script>
document.write("<script src='after.js'><\/script>");
</script>
 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-02 20:23:38