Ошибка загрузки окна в Chrome

Я добавляю некоторые теги <script/> из javascript для загрузки некоторых библиотек (например, jquery). Когда все библиотеки загружены, я выполняю основной код. Чтобы дождаться, пока все будет готово, я использую решение, аналогичное тому, что приведено в этом ответе. (нашла в Интернете).

Теперь история: http://jsfiddle.net/EH84z/

function load_javascript(src) {
    var a = document.createElement('script');
    a.type = 'text/javascript';
    a.src = src;
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(a, s);
}

load_javascript('http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js');

function addEvent(elm, evType, fn, useCapture) {
    //Credit: Function written by Scott Andrews
    //(slightly modified)
    var ret = 0;

    if (elm.addEventListener) {
        ret = elm.addEventListener(evType, fn, useCapture);
    } else if (elm.attachEvent) {
        ret = elm.attachEvent('on' + evType, fn);
    } else {
        elm['on' + evType] = fn;
    }

    return ret;
}

addEvent(window, "load", function() {
    console.log(window.jQuery + '  ' + window.$);
    $(document);
}, false);

Он отлично работает в Firefox, но довольно часто дает сбои в Chrome. Каждый второй раз, когда я нажимаю кнопку запуска jsfiddle, обратный вызов выполняется до загрузки JQuery, что приводит к ошибке в консоли Chrome.

Означает ли это, что я ужасно злоупотребляю addEventListener? Если да, то как правильно его использовать и как мне на самом деле дождаться загрузки всех скриптов?

Спасибо!
PS Пока не проверял его в других браузерах, поэтому, пожалуйста, прокомментируйте, если он не работает где-то еще.

редактировать
если я подожду одну секунду (используя setTimout) перед тестированием, вероятность успеха увеличится до 100%. Пример http://jsfiddle.net/EH84z/1/


person Nikita Rybak    schedule 08.10.2010    source источник
comment
Просто любопытно, почему вы пытаетесь динамически загрузить фреймворк?   -  person Nick Craver    schedule 08.10.2010
comment
@Nick Это виджет, который люди вставляют на свои страницы. Я мог бы дать им несколько тегов script и сказать поместить их в элемент head, но мне кажется, что это менее запутывает пользователя, когда все происходит под капотом.   -  person Nikita Rybak    schedule 08.10.2010
comment
Похоже, вы столкнулись с этой ошибкой dev.jquery.com/ticket/4196.   -  person Blair McMillan    schedule 08.10.2010
comment
Что, если jQuery уже загружен в другом месте? Включение его снова приведет к удалению всех плагинов, которые у них есть... иногда зависимость (как указано в большинстве плагинов jQuery) является лучшим вариантом.   -  person Nick Craver    schedule 08.10.2010
comment
@ Ник, я не загружаю его снова, если он уже есть. Но я проверю механизм зависимости, спасибо.   -  person Nikita Rybak    schedule 08.10.2010
comment
Также используйте более старый набор функций, если это возможно, 1.3 или 1.2 в худшем случае (хотя 1.3+ будет в порядке), если только вы каким-то образом не зависите от функций 1.4+ ... пользователи не могут включать несколько версий, поэтому лучше полагаться на одна версия позади, чтобы поддерживать как можно больше, но эй, если вам нужна функциональность 1.4+, то так оно и есть.   -  person Nick Craver    schedule 08.10.2010


Ответы (1)


Вы должны прикрепить событие load к тегу скрипта jQuery, а не к объекту window.

Попробуй это:

function load_javascript(src) {
    var a = document.createElement('script');
    a.type = 'text/javascript';
    a.src = src;
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(a, s);

    // attach it to the script tag
    addEvent(a, "load", function() {
        console.log(window.jQuery + '  ' + window.$);
        $(document);
    }, false);
}
person Luca Matteis    schedule 08.10.2010
comment
Просто искал событие загрузки скрипта. Ты подтолкнул меня на это. +1 - person spender; 08.10.2010
comment
отличается ли это, если вы прикрепите событие сначала, а затем установите свойство src? - person Caspar Kleijne; 08.10.2010
comment
+1, спасибо! Я, безусловно, могу использовать один прослушиватель событий для каждого тега script/link. Но тогда возникает другой вопрос: какая польза от события загрузки окна? Это упоминается во многих местах (например, ответ, который я связал). Что он делает тогда? - person Nikita Rybak; 08.10.2010
comment
@Nikita: событие загрузки объекта окна запускается, когда все ресурсы (документ, объекты, изображения, css и т. д.) завершили рендеринг ... тот, который находится в HTML ... а не те, которые вы добавляете динамически. Вероятно, вам нужно вызвать load_javascript(), когда окно запустит событие загрузки... вы не сможете манипулировать DOM, пока он не будет загружен. - person Luca Matteis; 08.10.2010