<script> 태그가로드되지 않았는지 확인하는 방법


111

<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+ polling은 모든 JS에 넣을 필요가없는 성가신 찌그러짐입니다.
David

2
스크립트 태그 주입을 사용하여 JSONP 요청을 할 때 당신은 또한 ...로드 실패를 확인 할 수 있습니다
schellsan

답변:


36

스크립트 태그에 대한 오류 이벤트가 없습니다. 성공한 시점을 알 수 있으며 시간 초과 후로드되지 않았다고 가정 할 수 있습니다.

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

7
"onload"리스너는 자바 스크립트 오류가 있어도 실행됩니다.
Luca Matteis

38
음, 파일이로드되고 파일 자체에 오류가 있으면 예,하지만 파일이 제공되지 않으면 onload가 실행되지 않습니다.
Diodeus-James MacFarlane

1
네, 사실입니다. 그래서 그가 어떤 종류의 오류를 찾고 있는지 좀 더 구체적으로 물어 보았습니다.
Luca Matteis

1
하지만 타임 아웃은 페이지의 코더가 제공해야합니다. 맞습니까? 따라서 코더는 브라우저에 대해 다른 시간 제한을 선택하고 스크립트로드 시간이 초과되었다고 가정 한 다음 나중에 성공하도록 할 수 있습니다. 아니면?
hippietrail 2011

6
스크립트 태그에 대한 onerror evnt가 있습니다. 리소스를 찾을 수 없을 때 발생합니다.
응웬 트란

24

html5 브라우저 만 신경 쓰는 경우 오류 이벤트를 사용할 수 있습니다 (오류 처리 전용이므로 KISS IMHO의 차세대 브라우저에서만 지원하는 것이 좋습니다).

사양에서 :

src 속성의 값이 빈 문자열이거나 확인할 수없는 경우 사용자 에이전트는 작업을 대기열에 넣어 error 라는 간단한 이벤트를 발생시켜야합니다. 요소에서 이러한 단계를 중단해야합니다.

~

로드로 인해 오류 (예 : DNS 오류 또는 HTTP 404 오류)가 발생한 경우 스크립트 블록 실행은 요소에서 error라는 간단한 이벤트를 발생시키는 것으로 구성되어야합니다.

즉, 오류가 발생하기 쉬운 폴링을 수행 할 필요가 없으며이를 async 및 defer 속성과 결합하여 스크립트가 페이지 렌더링을 차단하지 않도록 할 수 있습니다.

지연 (비동기 아님) 만 지원하는 레거시 웹 브라우저가 기본값 인 동기 차단 동작 대신 지연 동작으로 폴백하도록 비동기 특성이 지정된 경우에도 defer 특성을 지정할 수 있습니다.

http://www.w3.org/TR/html5/scripting-1.html#script 에 대한 추가 정보


1
jQuery와 같은 JSONP 구현에 대한 아이디어가 이것을 지원합니까? 여기에서 JSONP로드 실패 감지에 대해 읽은 모든 내용은 감지 할 수 없다고 말하지만 시간 초과는 해결 방법이 될 수 있으며 최신 버전의 JSONP에 시간 초과가 추가되었습니다. 이 답변은 시간 초과보다 더 나은 것을 제공하는 것 같습니다. 맞습니까?
hippietrail 2011

1
가능한 예?
rogerdpack

13
<script src="nonexistent.js" onerror="alert('error!')"></script> 바이올린
Rudey

@Rudey Uncaught SyntaxError: Unexpected token '<'(최신 Chrome)
daleyjem

@daleyjem은 자바 스크립트에 HTML 태그를 넣으려고 한 것 같습니다. <script src="nonexistent.js" onerror="alert('error!')"></script>JS가 아닌 HTML 파일에 있어야합니다.
Rudey

21

Erwinus의 스크립트는 훌륭하게 작동하지만 명확하게 코딩되지 않았습니다. 나는 그것을 정리하고 그것이 무엇을하는지 해독 할 자유를 얻었다. 다음과 같이 변경했습니다.

  • 의미있는 변수 이름
  • 의 사용 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
이 함수는 MSIE8-에서 캐시 된 스크립트에 대해 실패했기 때문에 jQuery의 $ .getScript 를 사용해야 했습니다. Unfortunatelly
Zathrus Writer 2013-06-04

@ZathrusWriter 더 나은 아이디어 일 것입니다. 알려 주셔서 감사합니다! 이 코드의 URL에 임의의 int를 추가하면 캐싱이 제거됩니다.
Aram Kocharyan 2013 년

2
예 Aram, 그것은 확실히 트릭을 할 것입니다. 그러나 그것은 또한 브라우저의 캐싱을 무효화 할 것입니다. 따라서 그러한 경우의 오버 헤드는 아마도 그만한 가치가 없을 것입니다;)
Zathrus Writer

@ZathrusWriter, jQuery 구현의 작동 방식은 무엇입니까?
Pacerier

@Pacerier 죄송합니다. 저는 jQuery 핵심 개발자가 아니기 때문에 대답 할 수 없습니다
Zathrus Writer 2014 년

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);
 })

}

Martin이 지적했듯이 다음과 같이 사용했습니다.

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"); });
Martin Wantke

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는 어디에서 왔습니까?
Naftali aka Neal

1
또한 크로스 브라우저 솔루션입니다 ;-)
Codebeat 2011-08-04

1
@Erwinus 나는 헤더를 확인하지 않았고, 내가 수행 한 빠른 크로스 브라우저 확인이었고 $ .getScript는 항상 문제없이 실행되었으므로 계속해서 고수했습니다 ... 당신은 스스로 시도해보십시오. XAMPP 여기
Zathrus Writer 2013-06-05

19
이것이 작동하든 안되든, 디버그는 고사하고 읽는 것은 정말 고통 스럽습니다. 그것은 꽤 형편없는 형식과 정말 끔찍한 코딩 스타일입니다. 변수 이름 지정만으로는 엉망입니다.
Thor84no

7
읽을 수있는 코드의 가치가 보이지 않는다면 (실제로 실행되는 코드를 변경하지 않고도 읽을 수있게 만들 수 있음), 당신과 당신의 코드와 함께 일해야하는 모든 사람에게 죄송합니다.
Thor84no 2014

10

자바 스크립트가 nonexistant.js오류를 반환하지 않았 는지 확인하려면 다음 http://fail.org/nonexistant.js과 같이 변수를 추가해야합니다.var isExecuted = true; 다음 스크립트 태그가로드 될 때 존재하는지 확인해야합니다.

그러나 nonexistant.js404 (존재한다는 의미)없이 반환 된 것을 확인하고 싶다면 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
작동하지만 실제로 원하는 것을 수행하지 않습니다.이 경우 실패하면 이벤트가 발생하지 않습니다. 변수를 폴링 할 필요가 없으며 몇 초 후에도 여전히 거짓이면 on-fail 콜백을 실행합니다.
David

어떤 종류의 오류를 검색하려고합니까? 로드하지 못했습니까? nonexstant.js에서 자바 스크립트를 실행하지 못 하셨나요? HTTP 응답 오류? 좀 더 설명해주세요.
Luca Matteis

위의 모든 것이 좋습니다. 그래도 404 오류에 특히 관심이 있습니다.
David

404, nonexistant.js 파일이 존재하지 않는지 확인하고 싶습니까? 그러나 그것이 오류를 반환하지 않았는지 확인하고 싶다면?
Luca Matteis

Hey David, this.readyState / ...가 참이 아니면 스크립트가로드되지 않은 것입니다. 기본적으로 onError입니다.
Cody

7

특수한 상황에서 문제를 해결하는 가장 신뢰할 수있는 방법이기 때문에 이것이 반대표를받지 않기를 바랍니다. 서버가 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이라고 말했습니다. 보안 측면에서 스크립트를 정상적으로로드하는 것과 다르지 않기 때문입니다. 실제로 John Resig는 더 좋은 태그를 갖도록 비슷한 기술을 제안했습니다 ( http://ejohn.org/blog/degrading-script-tags/ ).

이 메서드를 사용하면 평가에서로드를 분리하고 평가가 발생하기 전후에 함수를 실행할 수 있습니다. 스크립트를 병렬로로드하지만 차례로 평가할 때 매우 유용합니다. HTML에 태그를 배치하면 브라우저가 쉽게 할 수 있지만 자바 스크립트를 사용하여 런타임에 스크립트를 추가하는 것은 허용하지 않습니다.

CORS는 스크립트를로드 할 때 JSONP보다 선호됩니다 ( http://en.wikipedia.org/wiki/XMLHttpRequest#Cross-domain_requests ). 그러나 다른 사이트에 임베드 할 자체 타사 위젯을 개발하는 경우 실제로 자체 iframe의 자체 도메인에서 Javascript 파일을로드해야합니다 (다시 AJAX 사용).

요컨대 :

  1. AJAX GET을 사용하여 리소스를로드 할 수 있는지 확인하십시오.

  2. 성공적으로로드 된 후 eval 사용

개선하려면 :

  1. 전송되는 캐시 제어 헤더를 확인하십시오.

  2. 필요한 경우 localStorage의 콘텐츠 캐싱을 살펴보십시오.

  3. 더 깨끗한 코드를 위해 Resig의 "degrading javascript"를 확인하십시오.

  4. require.js 확인


이 방법을 사용하려면 원 서버가 CORS를 활성화해야합니다. 항상 그런 것은 아닙니다.
rogerdpack

5

이 트릭은 나를 위해 일했지만 이것이 아마도이 문제를 해결하는 가장 좋은 방법은 아니라는 것을 인정합니다. 이것을 시도하는 대신 자바 스크립트가로드되지 않는 이유를 확인해야합니다. 서버 등에 스크립트의 로컬 사본을 보관하거나 스크립트를 다운로드하려는 타사 공급 업체에 확인하십시오.

어쨌든, 해결 방법은 다음과 같습니다. 1) 변수를 false로 초기화 2) 자바 스크립트가로드 될 때 true로 설정 (onload 속성 사용) 3) HTML 본문이로드되면 변수가 true인지 false인지 확인합니다.

<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에 스크립트를 삽입해야하는 경우 다른 접근 방식이 필요합니다.
Jamey Sharp

훌륭한 솔루션입니다. 왜 찬성되지 않았는지 이해할 수 없습니다.
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 2013

2
예. 기억 하겠지만,이 접근 방식에는 제한이 있습니다. 이러한 방식으로 많은 스크립트를로드 할 수 없습니다. --- 내가 올바르게 기억한다면 교차 도메인 스크립팅 제한으로 인해.
osa

jQuery (또는 다른 라이브러리) 사용의 문제는 먼저 해당 라이브러리를로드해야한다는 것입니다. 그렇다면 해당 라이브러리가로드되지 않았 는지 어떻게 확인 합니까?
Pacerier

이 방법도 사용했지만 cache:true$ .getScript 호출에 사용 하는 것이 좋습니다 (기본적으로 꺼져 있음). 이렇게하면 대부분의 요청에 대해 getScript 호출에 대해 캐시 된 버전을 자동으로 사용합니다 (대기 시간 절약)
Laurens Rietveld

2

이것은 promise를 사용하여 안전하게 수행 할 수 있습니다.

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에는 아무런 차이가 없습니다. 여전히 오류 처리기를 실행하지 않습니다.
David

나는 사파리에서 onclick 핸들러에 문제가 있었고 이것이 수정했기 때문에 onerror에서도 동일하다고 생각했습니다. 분명히하지 ...

1
정적으로 포함 된 스크립트 태그에 대해서도 작동해야합니까, 아니면 동적으로 주입 된 태그에만 작동합니까? jQuery가로드되지 않았는지 감지하는 데 사용하려고했지만 작동하지 않았습니다. 내가 잘못하고 있는지 아니면이 경우 작동하지 않는지 확실하지 않습니다.
hippietrail 2011

1
@hippietrail-이벤트 리스너는 정적 HTML에서 작동하지 않습니다 <script>. 이전에 추가하려고하면 태그가 존재하지 않는다는 오류가 발생하고 이후에 추가하면 스크립트가 이미 실행되어 해당 이벤트를 트리거합니다. 유일한 방법은 스크립트로 인한 부작용을 찾는 것입니다.

감사합니다. 이것이 JS 오류가 아닌 404에서만 작동한다는 것이 너무 나쁩니다. 스크립트 내부에 변수를 설정하는 것이 항상 가능한 것은 아닙니다.
Jo Liss

0

타임 아웃을 설정 한 다음 타임 아웃 후로드 실패를 가정하는 것이 제안되었습니다.

setTimeout(fireCustomOnerror, 4000);

그 접근 방식의 문제는 가정이 우연에 근거한다는 것입니다. 제한 시간이 만료 된 후에도 요청은 여전히 ​​보류 중입니다. 프로그래머가로드가 발생하지 않는다고 가정 한 후에도 보류중인 스크립트에 대한 요청이로드 될 수 있습니다.

요청을 취소 할 수있는 경우 프로그램은 일정 기간 동안 기다린 다음 요청을 취소 할 수 있습니다.


0

이것이 창 개체에서 방출되는 로딩 오류를 감지하기 위해 promise를 사용한 방법입니다.

<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 파일 내용을 검색합니다. 이 작업이 완료되면 상태 코드를 확인하여 이것이 성공했는지 여부를 결정할 수 있습니다. 그런 다음 xhr 객체에서 responseText를 가져와 try / catch로 래핑하고 동적으로 스크립트 태그를 만들고 IE의 경우 스크립트 태그의 text 속성을 JS 텍스트로 설정할 수 있습니다. 다른 모든 브라우저에서 내용이있는 텍스트 노드를 스크립트 태그에 추가합니다. 스크립트 태그가 실제로 파일의 src 위치를 포함 할 것으로 예상하는 코드가있는 경우 작동하지 않지만 대부분의 상황에서는 괜찮습니다.


이 솔루션은 최신 브라우저에서 사용되지 않습니다.
Simon_Weaver

0

onerror 이벤트

* 2017 년 8 월 업데이트 : onerror는 Chrome 및 Firefox에서 실행됩니다. onload는 Internet Explorer에 의해 시작됩니다. Edge는 onerror도 onload도 실행하지 않습니다. 이 방법을 사용하지는 않지만 경우에 따라 작동 할 수 있습니다. 또한보십시오

<link> onerror는 IE에서 작동하지 않습니다.

*

정의 및 사용 onerror 이벤트는 외부 파일 (예 : 문서 또는 이미지)을로드하는 동안 오류가 발생하면 트리거됩니다.

팁 : 오디오 / 비디오 미디어에서 사용할 때 미디어로드 프로세스에 어떤 종류의 방해가있을 때 발생하는 관련 이벤트는 다음과 같습니다.

  • 중단하다
  • 비어있는
  • 설치
  • onsuspend

HTML에서 :

요소 onerror = "myScript">

JavaScript 에서 addEventListener () 메서드를 사용합니다.

object.addEventListener ( "error", myScript);

참고 : addEventListener () 메서드는 Internet Explorer 8 및 이전 버전에서 지원되지 않습니다.

예제 이미지를로드 할 때 오류가 발생하면 JavaScript를 실행합니다.

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.