Нужно ли использовать window.onReady () после асинхронного встраивания скрипта? - PullRequest
1 голос
/ 16 апреля 2011

Я реализую функциональность, которая загружает скрипт асинхронно. После завершения XHR я вставляю код в документ и вызываю метод обратного вызова. Метод обратного вызова использует этот динамически загруженный код.

Что мне интересно, так это то, что мой обратный вызов вызывается до разбора добавленного скрипта? Нужно ли использовать window.onReady () и позволить браузеру обработать добавленный скрипт и запустить window.onReady (), а затем просто вызвать мой метод обратного вызова?

Пожалуйста, не говорите мне использовать <your favority library here>, потому что я делаю это, чтобы выучить.

Edit: Или я должен вставить элемент script с установленными src и async и прослушать событие readystatechange элемента script?

Ответы [ 3 ]

1 голос
/ 16 апреля 2011

Или я должен вставить элемент сценария с набором src и async и прослушать событие readystatechange элемента сценария

Самый надежный способ - вставить элемент scriptс набором src (не устанавливать async или defer, нет необходимости).Для уведомления о том, что скрипт был загружен и проанализирован, выполните одно из двух действий:

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

    Пример ( живая копия ):

    Скрипт:

    function foo() {
        display("foo() called");
    }
    callWhenReady();
    

    Скрипт, загружающий его:

    var script;
    display("Loading script " + url + "...");
    script = document.createElement('script');
    script.src = url;
    document.body.appendChild(script);
    
    function callWhenReady() {
      display("Script says it's ready, calling foo...");
      foo();
    }
    
  2. Используйте самовосстановляющийся цикл setTimeout для поиска символа, который определяет скрипт (предположительно, вы знаете,один, вы хотите позвонить в него).Или вы можете использовать setInterval, но для этого необходимо, чтобы вы отслеживали ручку таймера, и, честно говоря, я предпочитаю тот контроль, который дает мне самореспланирование setTimeout.

    Пример ( livecopy ):

    Сценарий (примечание без обратного вызова):

    function foo() {
        display("foo() called");
    }
    

    Сценарий загрузки:

    var script;
    display("Loading script " + url + "...");
    script = document.createElement('script');
    script.src = url;
    document.body.appendChild(script);
    watchFor('foo');
    
    function watchFor(fname) {
      if (typeof foo === "function") {
        display("foo detected! Calling...");
        foo();
      }
      else {
        // Not found yet, wait
        setTimeout(function() {
          watchFor(fname);
        }, 50);
      }
    }
    
  3. Обновление : прокомментируйте ваш комментарий ниже: Если вы действительно знаете ничего о загружаемом скрипте, и вы не можете заставить скрипт вызывать вас, мне непонятно, зачем вам это нужнополучить событие.(Что вы будете делать, если вы не знаете ни одного из его глобальных символов и поэтому не можете вызывать какие-либо функции, которые он добавляет?) Но большинство браузеров поддерживают событие load для элементов script и для тех, которые неt (более ранние IE, в основном), есть событие readystatechange.В этой ситуации вы можете использовать комбинацию из них:

    Пример ( живая копия ):

    var script;
    display("Loading script " + url + "...");
    script = document.createElement('script');
    script.onload = function() {
      display("Script loaded (notification via load event). Calling foo just to prove it's loaded, but in the question we wouldn't know about the symbol do we wouldn't be able to call it.");
      foo();
    };
    script.onreadystatechange = function() {
      if (script.readyState === "loaded") {
        display("Script loaded (notificaton via readyState). Calling foo just to prove it's loaded, but in the question we wouldn't know about the symbol do we wouldn't be able to call it.");
        foo();
      }
    };
    document.body.appendChild(script);
    script.src = url;
    

    Это работает через событие load в Chrome 10Firefox 3.6, Safari 5 и Mobile Safari;через событие readystatechange в IE6, IE7 и IE8;и через оба события в Opera 11 и IE9.

1 голос
/ 16 апреля 2011

Это зависит от того, что вы хотите сделать в вашем скрипте

Вот пример внедрения в скрипт до того, как dom будет готов, и вызов функции обратного вызова.

var callback = function() { console.log('hi you called'); };

document.write('<script type="text/javascript" charset="utf-8">// code\n callback();<\/script>');

Если сценарий должен работать с dom, ему нужно подождать, пока он не будет готов, в противном случае - нет.

Однако ваше решение необходимо будет протестировать во всех браузерах, которые вы хотите поддерживать, как порядок оценки сценария иисполнение отличается, например, от IE и FF.

1 голос
/ 16 апреля 2011

Это действительно зависит от того, как вы его загружаете.

Вы можете загрузить скрипт, а затем просто выполнить eval () responseText после его загрузки.

Или вы также можете document.createElement('script'), а затем вызвать метод обратного вызова.

Pusuedocode:

load_xhr('path/to/js', function onReady (responseText) {

eval(responseText);

//OR

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

script.text = responseText;

//Append element to DOM

//THEN

callback_method();

});

Редактировать: Или я должен вставить скрипт элемент с набором src и async, и слушать элементы скрипта событие readystatechange?

Если вы сделаете это, появится символ загрузки браузера. Если вы загрузите его через XHR, пользователь ничего не заметит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...