Bir <script> etiketinin yüklenemediğini nasıl anlarsınız?


112

Dinamik <script>olarak bir sayfaya etiket ekliyorum <head>ve yüklemenin bir şekilde başarısız olup olmadığını söylemek istiyorum - bir 404, yüklenen komut dosyasında bir komut dosyası hatası, ne olursa olsun.

Firefox'ta bu çalışır:

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

Ancak, bu IE veya Safari'de çalışmaz.

Bunu Firefox dışındaki tarayıcılarda çalıştırmanın bir yolunu bilen var mı?

(.Js dosyalarının içine özel kod yerleştirmeyi gerektiren bir çözümün iyi bir çözüm olduğunu düşünmüyorum. Uygun değildir ve esnek değildir.)


4
Büyük web sitesi, ajax aracılığıyla yüklenen içerik için bağımlılıkların otomatik yüklenmesi. if+ anket, tüm JS'ye eklemek istemediğim can sıkıcı bir sorun.
David

2
Komut dosyası etiketi yerleştirmeyi kullanarak bir JSONP isteği yaparken yükleme hatasını da kontrol etmek isteyebilirsiniz ...
schellsan

Yanıtlar:


36

Komut dosyası etiketi için hata olayı yok. Ne zaman başarılı olduğunu anlayabilir ve bir zaman aşımından sonra yüklenmediğini varsayabilirsiniz:

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

7
Bir javascript hatası olsa bile "yükleme" dinleyicisi çalıştırılacaktır.
Luca Matteis

38
Evet, eğer dosya LOADS ise ve dosyanın kendisinde bir hata varsa, ancak dosya sunulmazsa, onload asla ateşlenmez.
Diodeus - James MacFarlane

1
evet, doğru, bu yüzden ne tür bir hata aradığı konusunda daha spesifik olmayı istedim.
Luca Matteis

1
Ancak zaman aşımı sayfanın kodlayıcısı tarafından sağlanmalıdır, değil mi? Bu nedenle, kodlayıcı tarayıcı için farklı bir zaman aşımı seçebilir, komut dosyası yüklemesinin zaman aşımına uğradığını varsayabilir ve ardından bir süre sonra başarılı olmasını sağlayabilir. Ya da değil?
hippietrail

6
Komut dosyası etiketi için bir hata yok. Kaynak bulunamadığında ateşlenecektir.
Nguyen Tran

24

Yalnızca html5 tarayıcıları ile ilgileniyorsanız, hata olayını kullanabilirsiniz (bu sadece hata işleme için olduğundan, bunu sadece KISS IMHO için yeni nesil tarayıcılarda desteklemeniz yeterli olacaktır).

Spesifikasyondan:

Src özniteliğinin değeri boş dizeyse veya çözülemezse, kullanıcı aracısının öğede hata adlı basit bir olayı tetiklemek için bir görevi kuyruğa alması ve bu adımları iptal etmesi gerekir .

~

Yükleme bir hatayla sonuçlandıysa (örneğin, bir DNS hatası veya bir HTTP 404 hatası), komut dosyası bloğunun yürütülmesi, öğede hata adlı basit bir olayın tetiklenmesinden ibaret olmalıdır.

Bu, hataya açık bir yoklama yapmanız gerekmediği ve komut dosyasının sayfa oluşturmayı engellemediğinden emin olmak için bunu eşzamansız ve erteleme özniteliğiyle birleştirebileceğiniz anlamına gelir:

Erteleme özniteliği, zaman uyumsuz özniteliği belirtilmiş olsa bile, yalnızca ertelemeyi destekleyen (ve eşzamansız değil) eski Web tarayıcılarının varsayılan eşzamanlı engelleme davranışı yerine erteleme davranışına geri dönmesine neden olmak için belirtilebilir.

Http://www.w3.org/TR/html5/scripting-1.html#script hakkında daha fazla bilgi


1
JQuery'deki gibi JSONP uygulamaları hakkında herhangi bir fikir bunu destekliyor mu? JSONP'nin yüklenemediğini tespit etmekle ilgili burada okuduğum her şey, bunun tespit edilemediğini söylüyor, ancak bir zaman aşımı bir geçici çözüm olabilir ve JSONP'nin son sürümüne bir zaman aşımı eklendi. Görünüşe göre bu yanıt zaman aşımından daha iyi bir şey sağlıyor - bu doğru mu?
hippietrail

1
örnek mümkün lütfen?
rogerdpack

13
<script src="nonexistent.js" onerror="alert('error!')"></script> fiddle
Rudey

@Rudey Uncaught SyntaxError: Unexpected token '<'(en son Chrome'da)
daleyjem

@daleyjem, JavaScript'e bir HTML etiketi koymaya çalışmışsınız gibi görünüyor. <script src="nonexistent.js" onerror="alert('error!')"></script>JS dosyanıza değil HTML dosyanıza gitmelisiniz.
Rudey

21

Erwinus'un senaryosu harika çalışıyor, ancak çok net bir şekilde kodlanmamış. Onu temizlemek ve ne yaptığını çözmek için özgürdüm. Şu değişiklikleri yaptım:

  • Anlamlı değişken isimleri
  • Kullanımı prototype.
  • require() bir bağımsız değişken kullanır
  • alert()Varsayılan olarak hiçbir mesaj döndürülmez
  • Aldığım bazı sözdizimi hataları ve kapsam sorunları düzeltildi

Tekrar Erwinus sayesinde, işlevselliğin kendisi belirgindir.

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'nin $ .getScript kodunu kullanmak zorunda kaldım , çünkü bu işlev MSIE8'de önbelleğe alınmış komut dosyaları için başarısız oldu, ne yazık ki
Zathrus Writer

@ZathrusWriter bu muhtemelen daha iyi bir fikir, bize bildirdiğiniz için teşekkürler! Muhtemelen bu koddaki url'ye rastgele bir int ekleyebilirsiniz ve bu, önbelleği kaldırır.
Aram Kocharyan

2
Evet Aram, bu kesinlikle işe yarar, ancak aynı zamanda tarayıcının önbelleğini de geçersiz kılar, bu yüzden böyle bir durumda ek yük muhtemelen buna değmez;)
Zathrus Writer

@ZathrusWriter, peki jQuery uygulamasının işleyişi nasıl çalışıyor?
Pacerier

@Pacerier üzgünüm, ben bir jQuery çekirdek geliştiricisi değilim, bu yüzden buna gerçekten cevap
veremiyorum

18

çalışan temiz çözümüm (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'in işaret ettiği gibi, şöyle kullandı:

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

VEYA

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

1
Aşağıdaki gibi kullanın:loaderScript("myscript.js").then(() => { console.log("loaded"); }).catch(() => { console.log("error"); });
Martin Wantke

17

Bunun eski bir konu olduğunu biliyorum ama size güzel bir çözüm buldum (sanırım). Tüm AJAX işlerini idare eden bir sınıfımdan kopyalandı.

Komut dosyası yüklenemediğinde, bir hata işleyicisi ayarlar, ancak hata işleyici desteklenmediğinde, 15 saniye boyunca hataları kontrol eden bir zamanlayıcıya geri döner.

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 nereden geldi?
Naftali aka Neal

1
Ve ayrıca, tarayıcılar arası bir çözümdür ;-)
Codebeat

1
@Erwinus Başlıkları kontrol etmedim, bu yaptığım hızlı bir çapraz tarayıcı kontrolüydü ve $ .getScript her zaman sorunsuz çalışıyordu, bu yüzden buna takılı kaldım ... kendiniz deneyebilirsiniz, W7 kullanıyorum ve XAMPP burada
Zathrus Writer

19
Bu işe yarasa da çalışmasa da, okuması acı verici - hata ayıklamayı bırakın. Bu oldukça zayıf bir biçimlendirme ve gerçekten acımasız bir kodlama stili. Değişken adlandırma tek başına bir karmaşa.
Thor84no

7
Okunabilir kodun değerini görmüyorsanız (ve gerçekten yürütülen kodda herhangi bir değişiklik yapmadan bunu okunabilir hale getirebiliyorsanız), sizinle ve kodunuzla çalışması gereken her bir kişi için üzülüyorum.
Thor84no

10

Javascript olmadığını kontrol etmek için nonexistant.jsdönen hiçbir hata bir değişken içini eklemek zorunda http://fail.org/nonexistant.jsgibi var isExecuted = true;ve komut dosyası etiketi yüklendiğinde varsa o zaman kontrol edin.

Ancak, yalnızca nonexistant.js404 olmadan döndürüldüğünü kontrol etmek istiyorsanız (yani var olduğu anlamına gelir), bir isLoadeddeğişkenle deneyebilirsiniz ...

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

Bu her iki durumu da kapsayacaktır.


1
Çalışıyor, ancak gerçekten istediğimi yapmıyor - bu durumda bir başarısızlık asla bir olayı tetiklemez. Bir değişken için anket yapmak zorunda kalmak istemiyorum ve birkaç saniye sonra hala yanlışsa, başarısız olduğunda geri aramayı başlat.
David

Ne tür bir hata almaya çalışıyorsunuz? Yüklenemiyor mu? Javascript nonexstant.js'de çalıştırılamıyor mu? HTTP Yanıtı Hatası? Lütfen daha açıklayıcı olun.
Luca Matteis

Yukarıdakilerden herhangi biri iyi olur. Yine de özellikle bir 404 hatasıyla ilgileniyorum.
David

404, yani nonexistant.js dosyasının mevcut olup olmadığını kontrol etmek mi istiyorsunuz? Ama eğer herhangi bir hata döndürüp döndürmediğini kontrol etmek istiyor musunuz?
Luca Matteis

Hey David, this.readyState / ... doğru değilse betiğin yüklenemediğini varsayabilmelisiniz. Temelde bir hata hatası.
Cody

7

Umarım bu, olumsuz oylanmaz, çünkü özel durumlarda sorunu çözmenin en güvenilir yolu budur. Sunucu, CORS ( http://en.wikipedia.org/wiki/Cross-origin_resource_sharing ) kullanarak bir Javascript kaynağı almanıza izin verdiğinde, bunu yapmak için zengin seçenekleriniz olur.

Kaynakları getirmek için XMLHttpRequest kullanmak, IE dahil tüm modern tarayıcılarda çalışacaktır. Javascript'i yüklemek istediğiniz için, ilk etapta kullanabileceğiniz Javascript'e sahipsiniz. ReadyState'i ( http://en.wikipedia.org/wiki/XMLHttpRequest#The_onreadystatechange_event_listener ) kullanarak ilerlemeyi takip edebilirsiniz . Son olarak, dosyanın içeriğini aldıktan sonra, eval () ile çalıştırabilirsiniz. Evet, eval dedim - çünkü güvenlik açısından komut dosyasını normal şekilde yüklemekten farklı değildir. Aslında, John Resig tarafından daha güzel etiketlere sahip olması için benzer bir teknik önerilmektedir ( http://ejohn.org/blog/degrading-script-tags/ ).

Bu yöntem ayrıca yüklemeyi eval'dan ayırmanıza ve eval gerçekleşmeden önce ve sonra işlevleri yürütmenize olanak tanır. Komut dosyalarını paralel olarak yüklerken, ancak bunları birbiri ardına değerlendirirken çok yararlı hale gelir - tarayıcıların etiketleri HTML'ye yerleştirdiğinizde kolayca yapabileceği bir şeydir, ancak Javascript ile çalışma zamanında komut dosyaları eklemenize izin vermez.

CORS, komut dosyalarını yüklemek için JSONP'ye tercih edilir ( http://en.wikipedia.org/wiki/XMLHttpRequest#Cross-domain_requests ). Bununla birlikte, diğer sitelere yerleştirilmek üzere kendi üçüncü taraf widget'larınızı geliştiriyorsanız, aslında Javascript dosyalarını kendi alanınızdan kendi iframe'inize yüklemelisiniz (yine AJAX kullanarak)

Kısacası:

  1. AJAX GET kullanarak kaynağı yükleyip yükleyemeyeceğinizi görmeye çalışın

  2. Başarıyla yüklendikten sonra eval kullanın

İyileştirmek için:

  1. Gönderilen önbellek kontrol başlıklarına göz atın

  2. Gerekirse, içeriği localStorage'da başka şekilde önbelleğe alma konusuna bakın.

  3. Daha temiz kod için Resig'in "küçültücü javascript" e bakın

  4. Require.js'ye göz atın


Not: Bu şekilde, kaynak sunucunun CORS'nin etkinleştirilmesini gerektirdiğini, ki bu her zaman geçerli veya kontrol edilemez: |
rogerdpack

5

Bu numara benim için çalıştı, ancak bunun muhtemelen bu sorunu çözmenin en iyi yolu olmadığını kabul etsem de. Bunu denemek yerine, javascriptlerin neden yüklenmediğini görmelisiniz. Komut dizisinin yerel bir kopyasını sunucunuzda vb. Tutmayı deneyin veya komut dosyasını indirmeye çalıştığınız üçüncü taraf satıcıya danışın.

Her neyse, işte geçici çözüm: 1) Bir değişkeni yanlış olarak başlatın 2) JavaScript yüklendiğinde (onload özelliğini kullanarak) bunu doğru olarak ayarlayın 3) HTML gövdesi yüklendikten sonra değişkenin doğru mu yoksa yanlış mı olduğunu kontrol edin

<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
Ya komut dosyası hala yükleniyorsa? Dosyanın bulunup bulunmadığını veya beklemeniz gerektiğini nasıl anlarsınız?
osa

Bu çözüm, komut dosyası etiketi doğrudan belge kaynağına yerleştirildiği sürece benim testimde işe yarar. Belgenin onload olayı, sayfa kaynağında başvurulan tüm kaynaklar zaten yüklenene (veya başarısız olana) kadar tetiklenmez. Daha sonra komut dosyalarını DOM'a eklemeniz gerekirse, başka bir yaklaşıma ihtiyacınız vardır.
Jamey Sharp

Harika çözüm. Neden olumlu oy verilmediğini anlamıyorum.
Lotfi

Bu, komut dosyasının eşzamanlı olarak yükleneceğini ve diğer her şeyin engelleneceğini varsayar, bu her zaman doğru değildir. Aslında, komut dosyalarını yüklemenin önerilen bir yolu değildir.
Vitim.us

4

İşte herhangi bir zamanlayıcı içermeyen JQuery tabanlı başka bir çözüm:

<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>

Teşekkürler: https://stackoverflow.com/a/14691735/1243926

Örnek kullanım ( JQuery getScript belgelerinden orijinal örnek ):

<!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>

Güzel Sergey! Öyleyse, dosyanın var olup olmadığını kontrol etmek için .get () ve hatasız çalıştırılıp / yüklenip yüklenemeyeceğini kontrol etmek için .getScript () mi kullanıyorsunuz?
jjwdesign

2
Evet. Hatırladığım kadarıyla, bu yaklaşımın sınırlamaları var: bu şekilde birçok komut dosyasını yükleyemezsiniz - eğer doğru hatırlıyorsam, etki alanları arası komut dosyası kısıtlamaları nedeniyle.
osa

JQuery'yi (veya başka bir kitaplığı) kullanmanın sorunu, önce bu kitaplığı yüklemeniz gerekmesidir. Peki bu kitaplığın yüklenip yüklenmediğini nasıl kontrol edersiniz ?
Pacerier

Ben de bu yaklaşımı cache:trueuyguladım , ancak $ .getScript çağrısı için kullanmanızı tavsiye ederim (bu varsayılan olarak kapalıdır). Bu şekilde, çoğu istek için, otomatik olarak getScript çağrısı için önbelleğe alınmış sürümü kullanır (gecikmeden tasarruf etmenizi sağlar)
Laurens Rietveld,

2

Bu, verilen sözler kullanılarak güvenle yapılabilir

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

ve bunun gibi kullan

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'de çalışmamasının nedeni, öznitelik sözdizimini kullanıyor olmanızdır. Bu yine de iyi çalışacak:

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

... IE dışında.

Başarılı bir şekilde yürütülen betiği kontrol etmek istiyorsanız, o betiği kullanarak bir değişken ayarlayın ve dış kodda ayarlanıp ayarlanmadığını kontrol edin.


Bu aslında Safari için herhangi bir fark yaratmaz - yine de hata işleyiciyi çalıştırmaz.
David

Safaride bir onclick işleyiciyle ilgili bir sorunum vardı ve bu sorunu çözdü, bu yüzden hata için de aynı olacağını düşündüm. Görünüşe göre değil ...

1
Bu, statik olarak dahil edilen komut dosyası etiketleri için mi yoksa sadece dinamik olarak enjekte edilenler için mi çalışmalıdır? JQuery'nin yüklenemediğini tespit etmek için kullanmaya çalıştım ama işe yaramadı. Yanlış mı yapıyorum, yoksa bu durumda işe yaramıyor mu emin değilim.
hippietrail

1
@hippietrail - bir olay dinleyicisi asla statik bir HTML üzerinde çalışmaz <script>. Daha önce eklemeye çalışırsanız, etiketin bulunmadığına dair bir hata alırsınız ve daha sonra eklerseniz, komut dosyası zaten çalışır ve olaylarını tetikler. Bunun tek yolu, betiğin neden olduğu yan etkileri aramaktır.

Teşekkürler flussence. Bunun JS hataları için değil, yalnızca 404 için çalışması çok kötü. Komut dosyası içinde bir değişken ayarlamak her zaman pratik değildir.
Jo Liss

1

onerror olayı

* Ağustos 2017 Güncellemesi: Chrome ve Firefox tarafından bir hata tetiklendi. onload, Internet Explorer tarafından tetiklenir. Edge ne bir hata ne de yükte ateşlemez. Bu yöntemi kullanmazdım ama bazı durumlarda işe yarayabilir. Ayrıca bakınız

<link> onerror IE'de çalışmıyor

*

Tanım ve Kullanım Harici bir dosya (örneğin bir belge veya bir görüntü) yüklenirken bir hata meydana gelirse, onerror olayı tetiklenir.

İpucu: Ses / video medyasında kullanıldığında, medya yükleme işleminde bir tür rahatsızlık olduğunda meydana gelen ilgili olaylar şunlardır:

  • onabort
  • onemptied
  • onstalled
  • onsuspend

HTML'de:

öğe onerror = "myScript">

JavaScript'te , addEventListener () yöntemini kullanarak:

object.addEventListener ("error", myScript);

Not: addEventListener () yöntemi, Internet Explorer 8 ve önceki sürümlerde desteklenmez.

Örnek Bir görüntüyü yüklerken bir hata oluşursa bir JavaScript çalıştırın:

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


0

Bir zaman aşımının ayarlanması ve ardından bir zaman aşımından sonra yük arızasının varsayılması önerildi.

setTimeout(fireCustomOnerror, 4000);

Bu yaklaşımdaki sorun, varsayımın tesadüfe dayalı olmasıdır. Zaman aşımınızın süresi dolduktan sonra istek hala beklemededir. Bekleyen komut dosyası için istek, programcı yüklemenin olmayacağını varsaydıktan sonra bile yüklenebilir.

Talep iptal edilebiliyorsa, program bir süre bekleyebilir ve ardından isteği iptal edebilir.


0

Pencere nesnesinde yayılan yükleme hatalarını tespit etmek için bir sözü böyle kullandım:

<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

İstediğin her şeyi yapmanın tek yolu çok çirkin olmak. Javascript dosya içeriğini almak için önce bir AJAX çağrısı gerçekleştirin. Bu tamamlandığında, bunun başarılı olup olmadığına karar vermek için durum kodunu kontrol edebilirsiniz. Ardından, responseText öğesini xhr nesnesinden alın ve bir dene / yakala içine sarın, dinamik olarak bir komut dosyası etiketi oluşturun ve IE için komut dosyası etiketinin text özelliğini JS metnine ayarlayabilirsiniz, diğer tüm tarayıcılarda yapabilmeniz gerekir komut dosyası etiketine içeriği olan bir metin düğümü ekleyin. Bir betik etiketinin dosyanın src konumunu gerçekten içermesini bekleyen herhangi bir kod varsa, bu işe yaramaz, ancak çoğu durumda iyi olacaktır.


Bu çözüm, modern tarayıcılarda çok eskidir.
Simon_Weaver
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.