Как я могу контролировать порядок выполнения Javascript? - PullRequest
2 голосов
/ 02 апреля 2009

У меня проблемы с параллелизмом на веб-странице, которую я создаю. По сути, у меня есть три файла скриптов, которые я использую для хранения некоторых данных:

script1.js:

var myValue = 1;

script2.js:

var myValue = 2;

script3.js:

var myValue = 3;

И у меня есть одна страница, mypage.html , которая выглядит примерно так:

<html>
<script>
   function get_number()
   {
     var script_file = GetQueryStringValue( "run" );
     e = document.createElement('script');
     e.type='text/javascript';
     e.src = script_file + ".js"
     head.appendChild( e );

     document.write( myValue );
   }
</script>
<body onload="get_number()">
   <div onclick="get_number()">Click me!</div>
</body>
</html>

Основная идея этой страницы заключается в том, что вы можете запросить ее следующим образом: mypage.html?run=script1 который сказал бы функции get_number() динамически вставлять script1.js в mypage.htm. Затем я вызываю get_number() для отображения значения, загруженного из скрипта.

Теперь, я сократил вышесказанное до того, что я считаю релевантными частями, и я, очевидно, упустил кучу вещей. Мой настоящий код загружает большой массив значений и является более интересным ... Но я надеюсь, что кто-нибудь может помочь мне с этим независимо.

Я обнаружил, что в IE число отображается правильно.

В Firefox, Chrome и Safari я получаю сообщение о том, что myValue не определено. Однако, если я нажму созданный мной Click me div, число отобразится правильно. Итак, я знаю, что я правильно загружаю внешний файл javascript. Но он просто не загружен вовремя, чтобы моя get_number() функция работала правильно onload.

Теперь я немного взломал свой файл, чтобы функция get_number выглядела так:

 function get_number()
 {
   var script_file = GetQueryStringValue( "run" );
   e = document.createElement('script');
   e.type='text/javascript';
   e.src = script_file + ".js"
   head.appendChild( e );

   setTimeout( function() { document.write( myValue ), 10 } );
 }

setTimeout задерживается достаточно для обновления DOM и загрузки javascript в большинстве случаев. Но это полный взлом. Firefox стремится правильно загружать этот «улучшенный» код постоянно, в то время как Chrome и Safari удается получить значение примерно в 50% случаев.

Итак, я думаю, мне интересно, есть ли лучший способ выполнить то, что я пытаюсь сделать здесь? Очень важно, чтобы значение управлялось извне (строкой запроса), но кроме этого требования я очень гибок.

Ответы [ 2 ]

6 голосов
/ 02 апреля 2009

Этот метод динамической загрузки файлов сценариев с использованием методов DOM, таких как head.appendChild, является асинхронным, что означает, что страница не ждет, пока она загрузится, прежде чем выполнять какой-либо дополнительный код. Если вам не нужно это асинхронное поведение, вы можете загрузить их с обычными элементами в своем HTML или возиться с «синхронным» XMLHttpRequest, чтобы получить его, и eval (), чтобы запустить его.

Вы, вероятно, не хотите этого делать, потому что асинхронность в любом случае ускоряет загрузку всей страницы. Вероятно, вам просто нужно добавить логику, которая ожидает загрузки динамически загружаемого скрипта, прежде чем переходить к следующему фрагменту кода. Это может, однако, включать опрос с использованием setInterval (), пока вы не заметите, что переменная из включенного скрипта была определена. Или вы можете добавить код во включенном скрипте, который вызывает метод к тому, что его ожидало.

Или вы можете посмотреть, как jQuery делает что-то похожее, посмотреть, где определен метод ajax, особенно эти части ...

var script = document.createElement("script");

// then later ...

script.onload = script.onreadystatechange = function(){
    if ( !done && (!this.readyState ||
    this.readyState == "loaded" || this.readyState == "complete") ) {

        // do processing
            head.removeChild( script );
    }
};

// ...

head.appendChild(script);
3 голосов
/ 02 апреля 2009

Не могли бы вы, возможно, добавить вызов функции в ваши файлы скриптов, чтобы при запуске они вызывали функцию, которая выполняет

document.write( myValue );

Так что script1.js будет

var myValue = 1;
scriptLoaded();

и ваш главный файл будет иметь:

function scriptLoaded(){
   document.write( myValue );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...