Как узнать, не удалось ли загрузить тег <script>


112

Я динамически добавляю <script>теги к странице <head>, и я хотел бы иметь возможность узнать, не удалось ли каким-либо образом загрузить - 404, ошибка скрипта в загруженном скрипте и т. Д.

В Firefox это работает:

var script_tag = document.createElement('script');
script_tag.setAttribute('type', 'text/javascript');
script_tag.setAttribute('src', 'http://fail.org/nonexistant.js');
script_tag.onerror = function() { alert("Loading failed!"); }
document.getElementsByTagName('head')[0].appendChild(script_tag);

Однако это не работает в IE или Safari.

Кто-нибудь знает, как заставить эту работу работать в других браузерах, кроме Firefox?

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


4
Большой сайт, автоматическая загрузка зависимостей для контента, загружаемого через ajax. if+ опрос - это досадная ерунда, которую я не хочу помещать во все JS.
Дэвид

2
Вы также можете проверить сбой загрузки при выполнении запроса JSONP с помощью внедрения тега сценария ...
schellsan

2
Перейти к
ответу

Ответы:


36

Для тега сценария нет события ошибки. Вы можете сказать, когда он был успешным, и предположить, что он не загрузился после тайм-аута:

<script type="text/javascript" onload="loaded=1" src="....js"></script>

7
Слушатель onload будет запущен, даже если есть ошибка javascript.
Лука Маттеис,

38
Ну да, если файл ЗАГРУЖАЕТСЯ и в самом файле есть ошибка, но если файл не обслуживается, загрузка никогда не сработает.
Диодей - Джеймс Макфарлейн,

1
да, верно, поэтому я попросил уточнить, какую ошибку он ищет.
Лука Маттеис,

1
Но тайм-аут должен быть предоставлен кодировщиком страницы, верно? Таким образом, кодировщик может выбрать другой тайм-аут для браузера, предположить, что время загрузки скрипта истекло, а затем добиться успеха чуть позже. Или не?
hippietrail

6
Для тега скрипта есть ошибка onerror. Он сработает, когда ресурс не найден.
Nguyen Tran

24

Если вас интересуют только браузеры html5, вы можете использовать событие ошибки (поскольку это только для обработки ошибок, должно быть нормально поддерживать это только в браузерах следующего поколения для KISS IMHO).

Из спецификации:

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

~

Если загрузка привела к ошибке (например, ошибка DNS или ошибка HTTP 404), выполнение блока сценария должно состоять только из запуска простого события с именем error в элементе.

Это означает, что вам не нужно проводить опрос, подверженный ошибкам, и вы можете комбинировать его с атрибутами async и defer, чтобы убедиться, что сценарий не блокирует рендеринг страницы:

Атрибут defer может быть указан, даже если указан атрибут async, чтобы унаследованные веб-браузеры, которые поддерживают только defer (а не async), возвращались к поведению отсрочки вместо поведения синхронной блокировки, которое используется по умолчанию.

Подробнее на http://www.w3.org/TR/html5/scripting-1.html#script


1
Любая идея реализации JSONP, например, в jQuery, поддерживает это? Все, что я читал здесь об обнаружении сбоев загрузки JSONP, говорит о том, что это невозможно обнаружить, но тайм-аут может быть обходным решением, и тайм-аут был добавлен в последнюю версию JSONP. Кажется, что этот ответ дает нечто большее, чем тайм-аут - это правильно?
hippietrail

1
пример можно пожалуйста?
rogerdpack

13
<script src="nonexistent.js" onerror="alert('error!')"></script> скрипку
Rudey

@Rudey Uncaught SyntaxError: Unexpected token '<'(в последней версии Chrome)
daleyjem

@daleyjem звучит так, будто вы пытались поместить HTML-тег в JavaScript. <script src="nonexistent.js" onerror="alert('error!')"></script>должен быть в вашем HTML-файле, а не в JS.
Руди,

21

Скрипт от Эрвинуса отлично работает, но не очень четко написан. Я взял на себя смелость очистить его и расшифровать, что он делал. Я внес эти изменения:

  • Значимые имена переменных
  • Использование prototype.
  • require() использует переменную аргумента
  • Нет alert()сообщений не возвращаются по умолчанию
  • Исправлены некоторые синтаксические ошибки и проблемы с областью действия, которые я получал

Еще раз спасибо Erwinus, сама функциональность на высоте.

function ScriptLoader() {
}

ScriptLoader.prototype = {

    timer: function (times, // number of times to try
                     delay, // delay per try
                     delayMore, // extra delay per try (additional to delay)
                     test, // called each try, timer stops if this returns true
                     failure, // called on failure
                     result // used internally, shouldn't be passed
            ) {
        var me = this;
        if (times == -1 || times > 0) {
            setTimeout(function () {
                result = (test()) ? 1 : 0;
                me.timer((result) ? 0 : (times > 0) ? --times : times, delay + ((delayMore) ? delayMore : 0), delayMore, test, failure, result);
            }, (result || delay < 0) ? 0.1 : delay);
        } else if (typeof failure == 'function') {
            setTimeout(failure, 1);
        }
    },

    addEvent: function (el, eventName, eventFunc) {
        if (typeof el != 'object') {
            return false;
        }

        if (el.addEventListener) {
            el.addEventListener(eventName, eventFunc, false);
            return true;
        }

        if (el.attachEvent) {
            el.attachEvent("on" + eventName, eventFunc);
            return true;
        }

        return false;
    },

    // add script to dom
    require: function (url, args) {
        var me = this;
        args = args || {};

        var scriptTag = document.createElement('script');
        var headTag = document.getElementsByTagName('head')[0];
        if (!headTag) {
            return false;
        }

        setTimeout(function () {
            var f = (typeof args.success == 'function') ? args.success : function () {
            };
            args.failure = (typeof args.failure == 'function') ? args.failure : function () {
            };
            var fail = function () {
                if (!scriptTag.__es) {
                    scriptTag.__es = true;
                    scriptTag.id = 'failed';
                    args.failure(scriptTag);
                }
            };
            scriptTag.onload = function () {
                scriptTag.id = 'loaded';
                f(scriptTag);
            };
            scriptTag.type = 'text/javascript';
            scriptTag.async = (typeof args.async == 'boolean') ? args.async : false;
            scriptTag.charset = 'utf-8';
            me.__es = false;
            me.addEvent(scriptTag, 'error', fail); // when supported
            // when error event is not supported fall back to timer
            me.timer(15, 1000, 0, function () {
                return (scriptTag.id == 'loaded');
            }, function () {
                if (scriptTag.id != 'loaded') {
                    fail();
                }
            });
            scriptTag.src = url;
            setTimeout(function () {
                try {
                    headTag.appendChild(scriptTag);
                } catch (e) {
                    fail();
                }
            }, 1);
        }, (typeof args.delay == 'number') ? args.delay : 1);
        return true;
    }
};

$(document).ready(function () {
    var loader = new ScriptLoader();
    loader.require('resources/templates.js', {
        async: true, success: function () {
            alert('loaded');
        }, failure: function () {
            alert('NOT loaded');
        }
    });
});

4
Я был вынужден использовать jQuery $ .getScript , так как эта функция не работала для кешированных скриптов в MSIE8-, к сожалению,
Zathrus Writer

@ZathrusWriter, возможно, это лучшая идея, спасибо, что сообщили нам! Вероятно, вы могли бы добавить случайный int к URL-адресу в этом коде, и это удалило бы кеширование.
Арам Кочарян

2
Да, Арам, это определенно поможет, однако это также приведет к недействительности кеширования браузера, так что накладные расходы в таком случае, вероятно, не того стоят;)
Zathrus Writer

@ZathrusWriter, так как же работает реализация jQuery?
Pacerier

@Pacerier, извините, я не разработчик ядра jQuery, поэтому я не могу ответить на этот вопрос
Zathrus Writer

18

мое рабочее чистое решение (2017)

function loaderScript(scriptUrl){
   return new Promise(function (res, rej) {
    let script = document.createElement('script');
    script.src = scriptUrl;
    script.type = 'text/javascript';
    script.onError = rej;
    script.async = true;
    script.onload = res;
    script.addEventListener('error',rej);
    script.addEventListener('load',res);
    document.head.appendChild(script);
 })

}

Как указал Мартин, использовал это так:

const event = loaderScript("myscript.js")
  .then(() => { console.log("loaded"); })
  .catch(() => { console.log("error"); });

ИЛИ

try{
 await loaderScript("myscript.js")
 console.log("loaded"); 
}catch{
 console.log("error");
}

1
Используйте его следующим образом:loaderScript("myscript.js").then(() => { console.log("loaded"); }).catch(() => { console.log("error"); });
Мартин Вантке,

17

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

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

function jsLoader()
{
    var o = this;

    // simple unstopable repeat timer, when t=-1 means endless, when function f() returns true it can be stopped
    o.timer = function(t, i, d, f, fend, b)
    {
        if( t == -1 || t > 0 )
        {
            setTimeout(function() {
                b=(f()) ? 1 : 0;
                o.timer((b) ? 0 : (t>0) ? --t : t, i+((d) ? d : 0), d, f, fend,b );
            }, (b || i < 0) ? 0.1 : i);
        }
        else if(typeof fend == 'function')
        {
            setTimeout(fend, 1);
        }
    };

    o.addEvent = function(el, eventName, eventFunc)
    {
        if(typeof el != 'object')
        {
            return false;
        }

        if(el.addEventListener)
        {
            el.addEventListener (eventName, eventFunc, false);
            return true;
        }

        if(el.attachEvent)
        {
            el.attachEvent("on" + eventName, eventFunc);
            return true;
        }

        return false;
    };

    // add script to dom
    o.require = function(s, delay, baSync, fCallback, fErr)
    {
        var oo = document.createElement('script'),
        oHead = document.getElementsByTagName('head')[0];
        if(!oHead)
        {
            return false;
        }

        setTimeout( function() {
            var f = (typeof fCallback == 'function') ? fCallback : function(){};
            fErr = (typeof fErr == 'function') ? fErr : function(){
                alert('require: Cannot load resource -'+s);
            },
            fe = function(){
                if(!oo.__es)
                {
                    oo.__es = true;
                    oo.id = 'failed';
                    fErr(oo);
                }
            };
            oo.onload = function() {
                oo.id = 'loaded';
                f(oo);
            };
            oo.type = 'text/javascript';
            oo.async = (typeof baSync == 'boolean') ? baSync : false;
            oo.charset = 'utf-8';
            o.__es = false;
            o.addEvent( oo, 'error', fe ); // when supported

            // when error event is not supported fall back to timer
            o.timer(15, 1000, 0, function() {
                return (oo.id == 'loaded');
            }, function(){ 
                if(oo.id != 'loaded'){
                    fe();
                }
            });
            oo.src = s;
            setTimeout(function() {
                try{
                    oHead.appendChild(oo);
                }catch(e){
                    fe();
                }
            },1); 
        }, (typeof delay == 'number') ? delay : 1);  
        return true;
    };

}

$(document).ready( function()
{
    var ol = new jsLoader();
    ol.require('myscript.js', 800, true, function(){
        alert('loaded');
    }, function() {
        alert('NOT loaded');
    });
});

4
... откуда взялся jQuery?
Нафтали, он же Нил,

1
Кроме того, это кроссбраузерное решение ;-)
Codebeat 04

1
@Erwinus Я не проверял заголовки, это была просто быстрая кроссбраузерная проверка, которую я выполнил, и $ .getScript всегда работал без проблем, поэтому я придерживался этого ... вы можете попробовать сами, я использую W7 и XAMPP здесь
Zathrus Writer 05

19
Работает это или нет, читать чертовски больно, не говоря уже об отладке. Это довольно плохое форматирование и действительно ужасный стиль кодирования. Одно только именование переменных - беспорядок.
Thor84no

7
Если вы не видите значения читаемого кода (и вы можете сделать его читаемым без каких-либо изменений в фактически выполняемом коде), то мне жаль каждого человека, который должен работать с вами и вашим кодом.
Thor84no

10

Чтобы проверить, nonexistant.jsне вернул ли javascript ошибку, вам нужно добавить переменную внутри http://fail.org/nonexistant.jslike, var isExecuted = true;а затем проверить, существует ли она при загрузке тега script.

Однако, если вы хотите только проверить, что nonexistant.jsвозвращается без 404 (что означает, что он существует), вы можете попробовать с isLoadedпеременной ...

var isExecuted = false;
var isLoaded = false;
script_tag.onload = script_tag.onreadystatechange = function() {
    if(!this.readyState ||
        this.readyState == "loaded" || this.readyState == "complete") {
        // script successfully loaded
        isLoaded = true;

        if(isExecuted) // no error
    }
}

Это покроет оба случая.


1
Это работает, но на самом деле не делает того, что я хочу - сбой в этом случае никогда не приведет к возникновению события. Я не хочу опрашивать переменную и, если через несколько секунд она все еще ложна, запускать обратный вызов при ошибке.
Дэвид

Какую ошибку вы пытаетесь исправить? Ошибка загрузки? Отказ выполнить javascript в nonexstant.js? Ошибка HTTP-ответа? Пожалуйста, будьте более информативными.
Лука Маттеис,

Любое из вышеперечисленного было бы хорошо. Однако меня особенно волнует ошибка 404.
Дэвид

404, то есть вы хотите проверить, не существует ли файл nonexistant.js? Но если вы хотите проверить, не вернул ли он ошибку?
Лука Маттеис,

Эй, Дэвид, ты должен быть в состоянии предположить, что если this.readyState / ... неверно, то скрипт не загрузился. В основном onError.
Cody

7

Я надеюсь, что это не будет отвергнуто, потому что в особых обстоятельствах это самый надежный способ решить проблему. Каждый раз, когда сервер позволяет вам получить ресурс Javascript с помощью CORS ( http://en.wikipedia.org/wiki/Cross-origin_resource_sharing ), у вас есть богатый набор возможностей для этого.

Использование XMLHttpRequest для извлечения ресурсов будет работать во всех современных браузерах, включая IE. Поскольку вы хотите загрузить Javascript, вам в первую очередь доступен Javascript. Вы можете отслеживать прогресс с помощью readyState ( http://en.wikipedia.org/wiki/XMLHttpRequest#The_onreadystatechange_event_listener ). Наконец, как только вы получите содержимое файла, вы можете выполнить его с помощью eval (). Да, я сказал eval - потому что с точки зрения безопасности это не отличается от обычной загрузки скрипта. Фактически, Джон Ресиг предлагает аналогичную технику для создания более удобных тегов ( http://ejohn.org/blog/degrading-script-tags/ ).

Этот метод также позволяет отделить загрузку от eval и выполнять функции до и после выполнения eval. Это становится очень полезным при параллельной загрузке скриптов, но при их оценке один за другим - браузеры могут легко это сделать, когда вы размещаете теги в HTML, но не позволяют вам, добавляя скрипты во время выполнения с помощью Javascript.

CORS также предпочтительнее JSONP для загрузки скриптов ( http://en.wikipedia.org/wiki/XMLHttpRequest#Cross-domain_requests ). Однако, если вы разрабатываете свои собственные сторонние виджеты для встраивания в другие сайты, вам следует фактически загрузить файлы Javascript из вашего собственного домена в свой собственный iframe (опять же, используя AJAX).

Коротко:

  1. Попробуйте посмотреть, сможете ли вы загрузить ресурс с помощью AJAX GET

  2. Используйте eval после успешной загрузки

Чтобы улучшить это:

  1. Проверьте отправленные заголовки управления кешем

  2. Посмотрите, как иначе кэшировать контент в localStorage, если вам нужно

  3. Посмотрите "деградирующий javascript" Resig, чтобы получить более чистый код.

  4. Посмотрите require.js


Обратите внимание: этот способ требует, чтобы на исходном сервере был включен CORS, что не всегда бывает так или управляемо: |
rogerdpack

5

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

В любом случае, вот обходной путь: 1) Инициализируйте переменную как false 2) Установите ее в true, когда загружается javascript (с использованием атрибута onload) 3) проверьте, является ли переменная истинной или ложной после загрузки тела HTML

<html>
  <head>
    <script>
      var scriptLoaded = false;

      function checkScriptLoaded() {
        if (scriptLoaded) {
          // do something here
        } else {
          // do something else here!
        }
      }
    </script>
    <script src="http://some-external-script.js" onload="scriptLoaded=true;" />
  </head>
  <body onload="checkScriptLoaded()">
    <p>My Test Page!</p>
  </body>
</html>

1
Что делать, если скрипт все еще загружается? Как узнать, что файл не найден или нужно просто подождать?
osa

Это решение работает в моем тестировании, если тег скрипта размещен непосредственно в источнике документа. Событие onload документа не срабатывает до тех пор, пока все ресурсы, указанные в источнике страницы, не будут загружены (или не будут загружены). Однако, если вам понадобится вставить скрипты в DOM позже, вам понадобится другой подход.
Джейми Шарп

Отличное решение. Я не понимаю, почему за него не проголосовали.
Lotfi

Это предполагает, что сценарий будет загружен синхронно, блокируя все остальное, что не всегда верно. На самом деле это не рекомендуемый способ загрузки скриптов.
Vitim.us

4

Вот еще одно решение на основе JQuery без таймеров:

<script type="text/javascript">
function loadScript(url, onsuccess, onerror) {
$.get(url)
    .done(function() {
        // File/url exists
        console.log("JS Loader: file exists, executing $.getScript "+url)
        $.getScript(url, function() {
            if (onsuccess) {
                console.log("JS Loader: Ok, loaded. Calling onsuccess() for " + url);
                onsuccess();
                console.log("JS Loader: done with onsuccess() for " + url);
            } else {
                console.log("JS Loader: Ok, loaded, no onsuccess() callback " + url)
            }
        });
    }).fail(function() {
            // File/url does not exist
            if (onerror) {
                console.error("JS Loader: probably 404 not found. Not calling $.getScript. Calling onerror() for " + url);
                onerror();
                console.error("JS Loader: done with onerror() for " + url);
            } else {
                console.error("JS Loader: probably 404 not found. Not calling $.getScript. No onerror() callback " + url);
            }
    });
}
</script>

Благодаря: https://stackoverflow.com/a/14691735/1243926

Пример использования (исходный образец из документации JQuery getScript ):

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>jQuery.getScript demo</title>
  <style>
  .block {
     background-color: blue;
     width: 150px;
     height: 70px;
     margin: 10px;
  }
  </style>
  <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>

<button id="go">&raquo; Run</button>
<div class="block"></div>

<script>


function loadScript(url, onsuccess, onerror) {
$.get(url)
    .done(function() {
        // File/url exists
        console.log("JS Loader: file exists, executing $.getScript "+url)
        $.getScript(url, function() {
            if (onsuccess) {
                console.log("JS Loader: Ok, loaded. Calling onsuccess() for " + url);
                onsuccess();
                console.log("JS Loader: done with onsuccess() for " + url);
            } else {
                console.log("JS Loader: Ok, loaded, no onsuccess() callback " + url)
            }
        });
    }).fail(function() {
            // File/url does not exist
            if (onerror) {
                console.error("JS Loader: probably 404 not found. Not calling $.getScript. Calling onerror() for " + url);
                onerror();
                console.error("JS Loader: done with onerror() for " + url);
            } else {
                console.error("JS Loader: probably 404 not found. Not calling $.getScript. No onerror() callback " + url);
            }
    });
}


loadScript("https://raw.github.com/jquery/jquery-color/master/jquery.color.js", function() {
  console.log("loaded jquery-color");
  $( "#go" ).click(function() {
    $( ".block" )
      .animate({
        backgroundColor: "rgb(255, 180, 180)"
      }, 1000 )
      .delay( 500 )
      .animate({
        backgroundColor: "olive"
      }, 1000 )
      .delay( 500 )
      .animate({
        backgroundColor: "#00f"
      }, 1000 );
  });
}, function() { console.error("Cannot load jquery-color"); });


</script>
</body>
</html>

Милый Сергей! Итак, вы используете .get (), чтобы проверить, существует ли файл, и .getScript (), чтобы проверить, может ли он быть выполнен / загружен без ошибок?
jjwdesign

2
Да. Насколько я помню, у этого подхода есть ограничения: вы не сможете загрузить таким образом много скриптов - если я правильно помню, из-за ограничений междоменного скриптинга.
osa

Проблема с использованием jQuery (или другой библиотеки) заключается в том, что вам нужно сначала загрузить эту библиотеку. Так как же проверить , не загрузилась ли эта библиотека?
Pacerier

Я тоже использовал этот подход, но рекомендую использовать его cache:trueдля вызова $ .getScript (по умолчанию он отключен). Таким образом, для большинства запросов он автоматически использует кешированную версию для вызова getScript (экономя время ожидания)
Лоуренс Ритвельд

2

Это можно безопасно сделать с помощью обещаний

function loadScript(src) {
  return new Promise(function(resolve, reject) {
    let script = document.createElement('script');
    script.src = src;

    script.onload = () => resolve(script);
    script.onerror = () => reject(new Error("Script load error: " + src));

    document.head.append(script);
  });
}

и использовать вот так

let promise = loadScript("https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js");

promise.then(
  script => alert(`${script.src} is loaded!`),
  error => alert(`Error: ${error.message}`)
);

1

Причина, по которой он не работает в Safari, заключается в том, что вы используете синтаксис атрибутов. Это будет работать нормально:

script_tag.addEventListener('error', function(){/*...*/}, true);

... кроме IE.

Если вы хотите проверить успешное выполнение сценария, просто установите переменную с помощью этого сценария и проверьте, задана ли она во внешнем коде.


На самом деле это не имеет значения для Safari - он по-прежнему не запускает обработчик ошибок.
Дэвид

У меня была проблема с обработчиком onclick в сафари, и это было ее исправлением, поэтому я подумал, что то же самое и с onerror. Видимо, нет ...

1
Должно ли это работать и для статически включенных тегов скрипта или только для динамически вводимых? Я просто попытался использовать его, чтобы определить, не удалось ли загрузить jQuery, но это не сработало. Я не уверен, что я делаю это неправильно или в данном случае это просто не работает.
hippietrail

1
@hippietrail - прослушиватель событий никогда не будет работать со статическим HTML <script>. Если вы попытаетесь добавить его раньше, вы получите сообщение об ошибке, что тег не существует, а если вы добавите его после, то сценарий уже запущен и инициировал свои события. Единственный способ - это искать побочные эффекты, вызванные скриптом.

Спасибо flussence. Жаль, что это работает только для 404, а не для ошибок JS. Установка переменной внутри скрипта не всегда возможна.
Jo Liss

1

onerror Событие

* Обновление от августа 2017 г .: onerror запускается Chrome и Firefox. onload запускается Internet Explorer. Edge не запускает ни ошибку, ни загрузку. Я бы не стал использовать этот метод, но в некоторых случаях он может работать. Смотрите также

<link> onerror не работает в IE

*

Определение и использование Событие onerror запускается, если возникает ошибка при загрузке внешнего файла (например, документа или изображения).

Совет: При использовании на аудио / видео носителях, связанные события, которые происходят, когда есть какие-то нарушения в процессе загрузки мультимедиа, включают:

  • OnAbort
  • один пустой
  • установленный
  • приостановить

В HTML:

element onerror = "myScript">

В JavaScript с помощью метода addEventListener ():

object.addEventListener («ошибка», myScript);

Примечание: Метод addEventListener () не поддерживается в Internet Explorer 8 и более ранних версиях.

пример Выполните JavaScript, если при загрузке изображения возникает ошибка:

img src = "image.gif" onerror = "myFunction ()">


0

Было предложено установить тайм-аут, а затем предполагать сбой нагрузки после тайм-аута.

setTimeout(fireCustomOnerror, 4000);

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

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


0

Вот как я использовал обещание для обнаружения ошибок загрузки, возникающих в объекте окна:

<script type='module'>
window.addEventListener('error', function(error) {
  let url = error.filename
  url = url.substring(0, (url.indexOf("#") == -1) ? url.length : url.indexOf("#"));
  url = url.substring(0, (url.indexOf("?") == -1) ? url.length : url.indexOf("?"));
  url = url.substring(url.lastIndexOf("/") + 1, url.length);
  window.scriptLoadReject && window.scriptLoadReject[url] && window.scriptLoadReject[url](error);
}, true);
window.boot=function boot() {
  const t=document.createElement('script');
  t.id='index.mjs';
  t.type='module';
  new Promise((resolve, reject) => {
    window.scriptLoadReject = window.scriptLoadReject || {};
    window.scriptLoadReject[t.id] = reject;
    t.addEventListener('error', reject);
    t.addEventListener('load', resolve); // Careful load is sometimes called even if errors prevent your script from running! This promise is only meant to catch errors while loading the file.
  }).catch((value) => {
    document.body.innerHTML='Error loading ' + t.id + '! Please reload this webpage.<br/>If this error persists, please try again later.<div><br/>' + t.id + ':' + value.lineno + ':' + value.colno + '<br/>' + (value && value.message);
  });
  t.src='./index.mjs'+'?'+new Date().getTime();
  document.head.appendChild(t);
};
</script>
<script nomodule>document.body.innerHTML='This website needs ES6 Modules!<br/>Please enable ES6 Modules and then reload this webpage.';</script>
</head>

<body onload="boot()" style="margin: 0;border: 0;padding: 0;text-align: center;">
  <noscript>This website needs JavaScript!<br/>Please enable JavaScript and then reload this webpage.</noscript>

0

Что ж, единственный способ, которым я могу делать все, что ты хочешь, довольно уродлив. Сначала выполните вызов AJAX, чтобы получить содержимое файла Javascript. Когда это будет завершено, вы можете проверить код состояния, чтобы решить, было ли это успешным или нет. Затем возьмите responseText из объекта xhr и оберните его в try / catch, динамически создайте тег скрипта, а для IE вы можете установить свойство text тега скрипта на текст JS, во всех других браузерах вы должны иметь возможность добавить текстовый узел с содержимым в тег скрипта. Если есть какой-либо код, который ожидает, что тег сценария действительно будет содержать местоположение файла src, это не сработает, но в большинстве ситуаций должно подойти.


Это решение устарело в современных браузерах.
Simon_Weaver
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.