Dostarczam widget javascript do kilku stron internetowych, które ładują asynchronicznie. Moje widget z kolei musi załadować skrypt dostarczany przez inną stronę, poza moją kontrolą.

Istnieje kilka sposobów sprawdzenia, czy ten skrypt został pomyślnie załadowany. Jednak musimy również uruchomić inny kod, jeśli obciążenie skryptu nie powiodło się.

Oczywiste narzędzia, które nie działają, obejmują:

  • Nie chcę używać bibliotek JavaScript, takich jak jQuery. Potrzebuję bardzo małego skryptu, aby zminimalizować mój wpływ na witryny, które korzystają z mojego widgetu.

  • Chcę wykryć awarię tak szybko, jak to możliwe, więc użycie zegara do sondowania jest niepożądane. Nie miałbym jednak nic przeciwko timerze jako ostatni ośrodek na starych przeglądarkach.

  • Znalazłem impreza <script> onerror, aby być zawodnym w niektórych głównych przeglądarkach. (Wydawało się, że zależy to, na którym zainstalowano dodatki).

  • Wszystko obejmujące document.write jest prosto. (Poza tym, że metoda jest iskrobezpieczne zły, mój kod jest załadowany asynchronicznie, więc document.write może zrobić złe rzeczy na stronie.)

Miałem poprzednie rozwiązanie, które obejmowały ładowanie <script> w nowym <iframe>. W takim IFrame, ustawić Handler zdarzeń <body onload=...>, który sprawdził, czy wydarzenie <script onload=...> zostało już zwolnione. Ponieważ <script> była częścią początkowego dokumentu, nie wstrzykiwany asynchronicznie później, onload opalany tylko po wykonaniu warstwy sieciowej za pomocą znacznika <script>.

Jednak teraz potrzebuję skryptu do załadowania w dokumencie macierzystym; Nie może być już w iframe. Potrzebuję więc innego sposobu wywołuje kodu, gdy tylko warstwa sieciowa została zrezygnowana, próbując pobrać skrypt.

Czytam "głębokie nurkowanie do mętnych wód ładowania skryptów" Próba wypracowania, jakiego zarządzenia gwarantuje, mogę liczyć na pomiędzy przeglądarek.

Jeśli rozumiem, że techniki są tam udokumentowane:

  • Muszę umieścić mój kod obsługi w osobnym pliku {x0}}.
  • Następnie, na niektórych przeglądarkach, mogę upewnić się, że mój kod działa dopiero po uruchomieniu skryptu trzecich lub nie powiodło się. Wymaga to przeglądarek, które wspierają:
    • Ustawianie atrybutu <script async> na false przez dom,
    • lub przy użyciu <script onreadystatechange=...> na IE 6 +.

Pomimo patrzenia na Tabela wsporczy ASync, nie mogę powiedzieć, czy mogę polegać na zamawianiu skryptu Wystarczająco Przeglądarki do tego mają być wykonane.

Jak więc mogę niezawodnie obsługiwać awarię podczas ładowania skryptu, którego nie kontroluję?

6
Jamey Sharp 26 listopad 2013, 06:18

2 odpowiedzi

Najlepsza odpowiedź

Wierzę, że rozwiązałem pytanie, które zadałem, choć okazuje się, że to nie rozwiązuje problemu, który naprawdę miałem. No cóż. Oto moje rozwiązanie:

Chcemy uruchomić jakiś kod po zakończeniu przeglądarki próbując załadować skrypt stron trzecich, abyśmy mogli sprawdzić, czy załadowano pomyślnie. Wykonujemy, że przez ograniczenie obciążenia skryptu wyboru nastąpiło dopiero po skrypcie trzeciego uruchomionego lub nie powiodło się. Skrypt fallback może następnie sprawdzić, czy skrypt stron trzecich stworzył Global, które miały.

Przeglądarka do przeglądarki Skrypt Ładowanie inspirowany przez http: //www.html5rocks. COM / PL / Tutoriale / Speed / Script-Loading /.

var fallbackLoader = doc.createElement(script),
    thirdPartyLoader = doc.createElement(script),
    thirdPartySrc = '<URL to third party script>',
    firstScript = doc.getElementsByTagName(script)[0];

// Doesn't matter when we fetch the fallback script, as long as
// it doesn't run early, so just set src once.
fallbackLoader.src = '<URL to fallback script>';

// IE starts fetching the fallback script here.

if('async' in firstScript) {
    // Browser support for script.async:
    // http://caniuse.com/#search=async
    //
    // By declaring both script tags non-async, we assert
    // that they need to run in the order that they're added
    // to the DOM.
    fallbackLoader.async = thirdPartyLoader.async = false;
    thirdPartyLoader.src = thirdPartySrc;
    doc.head.appendChild(thirdPartyLoader);
    doc.head.appendChild(fallbackLoader);
} else if(firstScript.readyState) {
    // Use readyState for IE 6-9. (IE 10+ supports async.)
    // This lets us fetch both scripts but refrain from
    // running them until we know that the fetch attempt has
    // finished for the first one.
    thirdPartyLoader.onreadystatechange = function() {
        if(thirdPartyLoader.readyState == 'loaded') {
            thirdPartyLoader.onreadystatechange = null;
            // The script-loading tutorial comments:
            // "can't just appendChild, old IE bug
            // if element isn't closed"
            firstScript.parentNode.insertBefore(thirdPartyLoader, firstScript);
            firstScript.parentNode.insertBefore(fallbackLoader, firstScript);
        }
    };
    // Don't set src until we've attached the
    // readystatechange handler, or we could miss the event.
    thirdPartyLoader.src = thirdPartySrc;
} else {
    // If the browser doesn't support async or readyState, we
    // just won't worry about the case where script loading
    // fails. This is <14% of browsers worldwide according to
    // caniuse.com, and hopefully script loading will succeed
    // often enough for them that this isn't a problem.
    //
    // If that isn't good enough, you might try setting an
    // onerror listener in this case. That still may not work,
    // but might get another small percentage of old browsers.
    // See
    // http://blog.lexspoon.org/2009/12/detecting-download-failures-with-script.html
    thirdPartyLoader.src = thirdPartySrc;
    firstScript.parentNode.insertBefore(thirdPartyLoader, firstScript);
}
2
Jamey Sharp 29 listopad 2013, 22:50

Czy rozważałeś za pomocą okna OnaError Handler? Spowoduje to wykrycie, gdy występują większość błędów, a potem możesz podjąć odpowiednie działania. Jako awansek na wszelkie problemy nie złapane w ten sposób można również chronić swój własny kod próbę / połów.

Powinieneś również sprawdzić, czy skrypt stronicowy faktycznie załadowany:

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

Następnie sprawdź, czy załadowano:

window.onload = function myLoadHandler() {
  if (loaded == null) {
    // The script doesn't exist or couldn't be loaded!
  }
}

Możesz sprawdzić, który skrypt spowodował błąd za pomocą parametru url.

window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
  if (url == third_party_script_url) {
    // Do alternate code
  } else {
    return false; // Do default error handling
  }
}
0
SpliFF 26 listopad 2013, 03:12