Подтвердить что ты не робот

Является ли обратный вызов jQuery getScript() ненадежным или я делаю что-то неправильно?

Я использую следующий бит script для загрузки другого:

$.getScript("CAGScript.js", function () {
    try {
        CAGinit();
    } catch(err) {
        console.log(err);
    }
});

Идея состоит в том, что $.getScript загружает script, а затем выполняет обратный вызов, когда это делается. CAGInit() - это функция, которая находится в CAGScript.js.

Проблема в том, что примерно половина времени CAGInit() не срабатывает (в любом браузере). Вход в консоль Firebug сообщает, что он не определен. В остальное время он отлично работает.

Есть ли у кого-нибудь идеи, что я делаю неправильно?

Спасибо.

4b9b3361

Ответ 1

Если файл хранится в том же домене, тогда jQuery будет использовать XHR для извлечения его содержимого, а затем глобально "eval". Это должно работать нормально, но если у вас возникли проблемы, я бы предложил использовать альтернативный метод вставки тега script. К сожалению, jQuery не раскрывает эту функциональность, поэтому вам придется сделать это самостоятельно:

var script = jQuery('<script/>').attr('src', 'CAGSCript.js').appendTo('head');

var timer = setInterval( function(){ 
    if (window.CAGInit !== undefined) {
        clearInterval(timer);
        script.remove();
        // Do your stuff:
        CAGInit();
    }
}, 200);

Лучше всего отнести это к функции; выше всего лишь пример...

Ответ 2

Я заметил ту же проблему с FF 3.6.

Решением является загрузка script синхронно.

Как упоминалось в документации jQuery, getScript сокращен для:

$.ajax({
  url: url,
  dataType: 'script',
  success: success
});

Все работает отлично, если вместо getScript использовать следующее:

$.ajax({
  url: url,
  dataType: 'script',
  success: success,
  async: false
});

Ответ 3

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

Ответ 4

У той же проблемы была проблема с firefox, и она немного переделала.

Применяя его к вашему примеру:

$.getScript("CAGScript.js", function (xhr) {
    try {
        CAGinit();
    } catch(err) {
        eval(xhr);
        CAGinit();
    }
});

В основном заставляет оценивать XHR-ответ, если он сам по себе не выполняет.

Ответ 5

Я тоже немного разбираюсь в Chrome. jQuery иногда вызывает обратный вызов успеха, как будто все хорошо, но script на самом деле не загружен должным образом. В нашем случае решение состояло в том, чтобы просто перейти от надежного jQuery:

<script>
    $.getScript("helpers.js", function () {
        // use helpers....or: EXPLODE (wheeeee!)
        helpers.doSomething();
    });
</script>

Чтобы доверять браузеру:

<script src="helpers.js"></script>
<script>
    helpers.doSomething();
</script>

Я снова и снова обнаруживаю, что "меньше jQuery == меньше случаев края == меньше ошибок". И обычно более читаемый код тоже!

Ответ 6

Чтобы убедиться, что CAGScript.js ЗАГРУЖЕН и ВЫПОЛНИЛСЯ до вызова функции CAGinit, самым верным способом является вызов функции внутри CAGScript.js.

CAGScript.js:



    ...
    /*
    your code
    */
    function CAGinit(){
    ...
    }
    ...
    /* last line */
    CAGinit();

а затем в вашем основном файле просто вызовите getScript():

 

    $.getScript("CAGScript.js");

Ответ 7

Да, я также обнаружил, что getScript ненадежен в FireFox, уворачивая обратный вызов до того, как script был загружен и/или выполнен. (Использование JQuery 1.41 и FireFox 3.6. Проблема, похоже, не затрагивает IE, Chrome или Opera.)

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

Предложение RaYell не работает, поскольку getScript сообщает об успехе, хотя script еще не был оценен. В большинстве случаев предложение Pieter заставляет код анализировать дважды, что является неэффективным и может вызвать ошибки.

Эта альтернатива, похоже, работает там, где getScript не работает. Обратите внимание, что это похоже на добавление элемента script DOM, тогда как getScript делает XHR.

http://www.diveintojavascript.com/projects/sidjs-load-javascript-and-stylesheets-on-demand

Ответ 8

Я думаю, вы можете начать с проверки функции testStatus функции обратного вызова, чтобы убедиться, что script действительно загружен. Функция обратного вызова имеет два параметра, более эффективные для тех, которые вы можете найти на jQuery Docs

$.getScript("CAGScript.js", function (data, textStatus) {
    if (textStatus === "success") {
        try {
            CAGinit();
        } catch(err) {
            console.log(err);
        }
    } else {
        console.log("script not loaded");
    }
});

Ответ 9

Я хотел иметь что-то похожее на auto_load в PHP, реализованном в JS, типичное решение использует try-catch для всех функций. Когда функция отсутствует, мы переходим к загрузке ее библиотеки. Мое решение взято из решения Pieter следующим образом:

function CheckUserPW(username,password){
    try{
       loginCheckUserPW(username,password);
    } catch(err) {
        $.getScript('login.js', function(xhr){ 
            eval(xhr);
            loginCheckUserPW(username,password);
        });
    }
}

Ответ 10

Кажется, что jQuery обрабатывает кросс-доменные и одни и те же запросы домена только сейчас. Для междоменных запросов он добавит тэг script и подпишится на ошибки и события загрузки и соответствующим образом вызовет ваши обратные вызовы и ошибки, это ошибка только в случае сбоя запроса, ошибки, оценивающие script, будут по-прежнему считаться успешными что касается запроса. Для одного и того же происхождения он выполнит запрос XHR, а затем выполнит команду globalEval и после этого вызовет ваш обратный вызов, если что-то не удастся в процессе, оно вызовет обратный вызов ошибки.

Использование XHR имеет несколько проблем, оно разбивает отладчик, sourcemaps и полагается на globalEval, у которого есть проблемы с ContentSecurityPolicy. Для этого мы просто добавляем тег script при загрузке скриптов.

var scriptElement = $("<script>").prop({src: url, async: true}); scriptElement.one('load', ()=> ...); scriptElement.one('error', (evt)=> ...); document.head.appendChild(scriptElement[0]);

Если вы хотите сделать это без поиска jQuery для динамического импорта скриптов в в этой статье

Надеюсь, это поможет.

Ответ 11

Мой способ

setTimeout(function(){ 
  $.getScript( "CAGScript.js");
  }, 
2000);

та же проблема, с которой мы сталкиваемся в angular, также когда мы хотим обновлять данные в $scope и решается с помощью $timeout таким же образом в angular...