динамически создаваемый скрипт: readyState никогда не «завершается» - PullRequest
10 голосов
/ 04 августа 2011

Я пытаюсь сделать что-то ПОСЛЕ полной загрузки скрипта.(IE8)

Скрипт, который я использую для тестирования: http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js
и неверный: http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.minaaaaaaaa.js

Код ...

var script = create the element and append to head...

// this works fine with FF/Chrome/...
script.onload = function() {alert('script loading complete');}
script.onerror = function() {alert('error loading script');}

// and for IE
script.onreadystatechange = function() {
    // this will alert 1.loading 2.loaded
    alert(this.readyState);

    // this never works
    if(this.readyState == 'complete') {alert('script loading complete');}

    // this works with either a valid or INVALID url
    else if(this.readyState == 'loaded') {alert('script loaded');}
};

Inв моем случае «complete» никогда не отображается, «загруженный» показывает, даже если URL недействителен.Таким образом, невозможно определить, ПРАВИЛЬНО ли загружен скрипт под IE.

Я что-то не так делаю?Почему я никогда не получаю полное состояние?

ОБНОВЛЕНИЕ

Хорошо, я только что прочитал несколько статей, и кажется, что readystate не является надежным способом обнаружения загрузки скрипта.

Так есть ли другой способ сделать это?без JQuery, но чистый Javascript.

Ответы [ 3 ]

11 голосов
/ 17 сентября 2013

Я обнаружил уловку, как сделать узел сценария «завершенным» в IE7 и IE8. А также, как определить, когда действительно происходит ошибка при загрузке скрипта (node.onerror работает только в IE9 +). Взлом в

  1. НЕ вставлять вновь созданный элемент в DOM (сразу).
  2. Вызов свойства node.children и проверка свойства node.onreadystate сразу после него. Если свойство изменяется на «завершено» - вы загрузили скрипт, оно меняется на «загрузка» - это наверняка ошибка загрузки скрипта.

Попробуй!

var node = document.createElement('script');
node.src = 'some-[un]existing-url.js';
node.type = 'text/javscript';

node.onreadystatechange = (function(node) { 
    return function () {
        if (/loaded|complete/.test(node.readyState)) {
            _finish();
        }
    };
})(node);

var _finish=function() {

        if (node.readyState == 'complete') {
            // insert node only after completing the request, though this is not necessary
            var head = document.head;
            head || (head = document.getElementsByTagName('head')[0]);
            head.appendChild(node);
            // call success function
            _success();
            return;
        }

        var firstState = node.readyState;

        // hack: calling 'children' property changes node's readyState from 'loaded' to complete
        // (if script was loaded normally) or to 'loading' - if error detected
        node.children;

        // error detected
        if (firstState == 'loaded' && node.readyState == 'loading') {
            // custom error code
            _error();
        }
}
5 голосов
/ 05 августа 2011

Согласно вашему комментарию, вот схема того, как динамически добавлять тег сценария с использованием XHR (XMLHttpRequest):

var handleRequest = function( ) { //!! set up the handleRequest callback

     if(this.status != undefined) {

         /* do something with the status code here */

     }

     if(this.readyState == 4) {

          var script = document.createElement("script") ;
              script.setAttribute("type","text/javascript") ;
          var text = document.createTextNode(this.responseText) ;
              script.appendChild(text) ;

          var head = document.getElementsByTagName("head")[0] ;
              head.insertBefore(script,head.firstChild) ;

     }

} ;

var request ; //!! supposing you have a way to get a working XHR Object

//.. set the XHR Object

request.open("GET",url,true) ;
request.overrideMimeType("text/javascript") ;
request.onreadystatechange = handleRequest ;
request.send(null) ;

Пожалуйста, имейте в виду, что это только для того, чтобы дать вам представление очто я имею в виду.Рабочий пример должен быть более сложным, если судить по исходному коду jQuery.


Ссылки:

0 голосов
/ 04 августа 2011

Обнаружение завершения загрузки

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

var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.onreadystatechange= function () {
  if (this.readyState == 'complete') helper();
}
script.onload= helper;
script.src= 'helper.js';
head.appendChild(script);

Здесь мы устанавливаем два разных обработчика событий для вновь созданного тега script.В зависимости от браузера, один или другой из этих двух обработчиков должен вызываться после завершения загрузки скрипта.Обработчик onreadystatechange работает только в IE.Обработчик onload работает в браузерах Gecko и Opera.

Тест "this.readyState == 'complete" "на самом деле не работает полностью.ReadyState теоретически проходит через ряд состояний:

  • 0 неинициализирован
  • 1 загрузка
  • 2 загружена
  • 3 интерактивна
  • 4 выполнено

Но на самом деле состояния могут быть пропущены.По моему опыту работы с IE 7 вы получаете либо загруженное событие, либо завершенное событие, но не оба.

Возможно, это связано с тем, загружаете ли вы из кэша или нет, но, похоже,другие факторы, которые влияют на то, какие события вы получаете.Иногда я получаю загрузку или интерактивные события, а иногда нет.Возможно, тест должен быть "this.readyState == 'загружен' || this.readyState == 'complete'", но это может вызвать срабатывание дважды.

http://unixpapa.com/js/dyna.html

ОБНОВЛЕНИЕ

Пожалуйста, вы можете заменить ваш script.onreadystatechange обратный вызов этим:

newjs.onreadystatechange = function () {
   if (newjs.readyState === 'loaded' || newjs.readyState === 'complete') {
      newjs.onreadystatechange = null;
      alert('script is complete or loaded.");
   }

};

Еще одна вещь, которую я заметил, это то, чтовы проводите сравнение строк с оператором ==.Это может вводить в заблуждение.Используйте === вместо этого.

...