Obsługa globalnych błędów JavaScript

Chciałbym wyłapać każdy błąd niezdefiniowanej funkcji. Czy istnieje globalna funkcja obsługi błędów w JavaScript? Przypadek użycia polega na przechwytywaniu wywołań funkcji z Flasha, które nie są zdefiniowane.

Author: sg7, 2009-06-04

10 answers

Czy to ci pomoże:

<script type="text/javascript">
window.onerror = function() {
    alert("Error caught");
};

xxx();
</script>

Nie jestem pewien, jak radzi sobie z błędami Flasha...

Aktualizacja: nie działa w Operze, ale hakuję Dragonfly, aby zobaczyć, co z tego wyjdzie. Sugestia dotycząca hakowania Dragonfly wynikła z tego pytania:

Okno Mimiczne. onerror w Operze przy użyciu javascript

 173
Author: Ionuț G. Stan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:10

Jak wyłapać nieobsługiwane błędy Javascript

Przypisanie zdarzenia window.onerror do obsługi zdarzenia takiego jak:

<script type="text/javascript">
window.onerror = function(msg, url, line, col, error) {
   // Note that col & error are new to the HTML 5 spec and may not be 
   // supported in every browser.  It worked for me in Chrome.
   var extra = !col ? '' : '\ncolumn: ' + col;
   extra += !error ? '' : '\nerror: ' + error;

   // You can view the information in an alert to see things working like this:
   alert("Error: " + msg + "\nurl: " + url + "\nline: " + line + extra);

   // TODO: Report this error via ajax so you can keep track
   //       of what pages have JS issues

   var suppressErrorAlert = true;
   // If you return true, then error alerts (like in older versions of 
   // Internet Explorer) will be suppressed.
   return suppressErrorAlert;
};
</script>

Zgodnie z komentarzem w kodzie, jeśli zwracaną wartością window.onerror jest true, przeglądarka powinna wyłączyć wyświetlanie okna dialogowego alertu.

Kiedy okno.OnError Event Fire?

W skrócie, zdarzenie jest podnoszone, gdy jedno z 1.) istnieje nieobowiązkowy wyjątek or 2.) występuje błąd czasu kompilacji.

Uncaught exceptions

  • throw "some messages"
  • call_something_undefined ();
  • cross_origin_iframe.contentWindow.document;, wyjątek bezpieczeństwa

Błąd kompilacji

  • <script>{</script>
  • <script>for(;)</script>
  • <script>"oops</script>
  • setTimeout("{", 10);, spróbuje skompilować pierwszy argument jako skrypt

Przeglądarki obsługujące okno.onerror

  • Chrome 13 +
  • Firefox 6.0+
  • Internet Explorer 5.5+
  • Opera 11.60 +
  • Safari 5.1+

Zrzut ekranu:

Przykład kodu onerror powyżej w akcji po dodaniu tego do strony testowej:

<script type="text/javascript">
call_something_undefined();
</script>

Alert Javascript pokazujący informacje o błędzie wyszczególnione przez okno.Zdarzenie onerror

JSFiddle:

Https://jsfiddle.net/nzfvm44d/

Bibliografia:

 589
Author: Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:45

Zaawansowana obsługa błędów

Jeśli obsługa błędów jest bardzo skomplikowana i dlatego może spowodować sam błąd, warto dodać flagę wskazującą, czy jesteś już w "trybie obsługi błędów". Tak:

var appIsHandlingError = false;

window.onerror = function() {
    if (!appIsHandlingError) {
        appIsHandlingError = true;
        handleError();
    }
};

function handleError() {
    // graceful error handling
    // if successful: appIsHandlingError = false;
}
W przeciwnym razie możesz znaleźć się w nieskończonej pętli.
 35
Author: SunnyRed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-30 18:31:44

Spróbuj Atatus , który zapewnia zaawansowane śledzenie błędów i monitorowanie rzeczywistych użytkowników dla nowoczesnych aplikacji internetowych.

Https://www.atatus.com/

Pozwól mi wyjaśnić, jak uzyskać stosy, które są w miarę kompletne we wszystkich przeglądarkach.

Obsługa błędów w JavaScript

Nowoczesne Chrome i Opera w pełni obsługują specyfikację HTML 5 dla ErrorEvent i window.onerror. W obu tych przeglądarkach możesz użyć window.onerror lub powiązać z "błędem" Zdarzenie poprawnie:

// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
    console.log(message, "from", error.stack);
    // You can send data to your server
    // sendError(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
    console.log(e.error.message, "from", e.error.stack);
    // You can send data to your server
    // sendError(data);
})

Niestety Firefox, Safari i IE są nadal w pobliżu i musimy je również wspierać. Ponieważ stacktrace nie jest dostępny w window.onerror, musimy zrobić trochę więcej pracy.

Okazuje się, że jedyne, co możemy zrobić, aby uzyskać ślady stosu od błędów, to zawinąć cały nasz kod w try{ }catch(e){ } blok, a następnie spojrzeć na e.stack. Możemy nieco ułatwić proces za pomocą funkcji o nazwie wrap, która przyjmuje funkcję i zwraca nową funkcję z dobrym błędem obsługa.

function wrap(func) {
    // Ensure we only wrap the function once.
    if (!func._wrapped) {
        func._wrapped = function () {
            try{
                func.apply(this, arguments);
            } catch(e) {
                console.log(e.message, "from", e.stack);
                // You can send data to your server
                // sendError(data);
                throw e;
            }
        }
    }
    return func._wrapped;
};
To działa. Każda funkcja, którą zawijasz ręcznie, będzie miała dobrą obsługę błędów, ale okazuje się, że w większości przypadków możemy to zrobić automatycznie.

Zmieniając globalną definicję addEventListener tak, aby automatycznie zawijała wywołanie zwrotne, możemy automatycznie wstawić try{ }catch(e){ } wokół większości kodu. Pozwala to na kontynuowanie działania istniejącego kodu, ale dodaje wysokiej jakości śledzenie WYJĄTKÓW.

var addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
    addEventListener.call(this, event, wrap(callback), bubble);
}

Musimy również upewnić się, że removeEventListener utrzymuje pracuję. W tej chwili nie będzie, ponieważ argument do addEventListener został zmieniony. Ponownie musimy to naprawić tylko na obiekcie prototype:

var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
    removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}

Przesyłanie danych o błędach do twojego zaplecza

Możesz wysłać dane o błędach za pomocą znacznika obrazu w następujący sposób

function sendError(data) {
    var img = newImage(),
        src = 'http://yourserver.com/jserror&data=' + encodeURIComponent(JSON.stringify(data));

    img.crossOrigin = 'anonymous';
    img.onload = function success() {
        console.log('success', data);
    };
    img.onerror = img.onabort = function failure() {
        console.error('failure', data);
    };
    img.src = src;
}

Zastrzeżenie: jestem web developerem w https://www.atatus.com/.

 21
Author: Fizer Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-01 05:40:06

Wydaje się, że window.onerror nie zapewnia dostępu do wszystkich możliwych błędów. Konkretnie ignoruje:

  1. <img> błędy ładowania (odpowiedź > = 400).
  2. <script> błędy ładowania (odpowiedź > = 400).
  3. globalne błędy jeśli masz wiele innych bibliotek w swojej aplikacji również manipulujących window.onerror w Nieznany sposób (jquery, angular, itp.).
  4. prawdopodobnie wiele przypadków, na które nie natknąłem się po zbadaniu tego teraz (iframes, stack overflow, itp.).

Oto początek skrypt, który wychwytuje wiele z tych błędów, dzięki czemu można dodać bardziej rozbudowane debugowanie do aplikacji podczas tworzenia.

(function(){

/**
 * Capture error data for debugging in web console.
 */

var captures = [];

/**
 * Wait until `window.onload`, so any external scripts
 * you might load have a chance to set their own error handlers,
 * which we don't want to override.
 */

window.addEventListener('load', onload);

/**
 * Custom global function to standardize 
 * window.onerror so it works like you'd think.
 *
 * @see http://www.quirksmode.org/dom/events/error.html
 */

window.onanyerror = window.onanyerror || onanyerrorx;

/**
 * Hook up all error handlers after window loads.
 */

function onload() {
  handleGlobal();
  handleXMLHttp();
  handleImage();
  handleScript();
  handleEvents();
}

/**
 * Handle global window events.
 */

function handleGlobal() {
  var onerrorx = window.onerror;
  window.addEventListener('error', onerror);

  function onerror(msg, url, line, col, error) {
    window.onanyerror.apply(this, arguments);
    if (onerrorx) return onerrorx.apply(null, arguments);
  }
}

/**
 * Handle ajax request errors.
 */

function handleXMLHttp() {
  var sendx = XMLHttpRequest.prototype.send;
  window.XMLHttpRequest.prototype.send = function(){
    handleAsync(this);
    return sendx.apply(this, arguments);
  };
}

/**
 * Handle image errors.
 */

function handleImage() {
  var ImageOriginal = window.Image;
  window.Image = ImageOverride;

  /**
   * New `Image` constructor. Might cause some problems,
   * but not sure yet. This is at least a start, and works on chrome.
   */

  function ImageOverride() {
    var img = new ImageOriginal;
    onnext(function(){ handleAsync(img); });
    return img;
  }
}

/**
 * Handle script errors.
 */

function handleScript() {
  var HTMLScriptElementOriginal = window.HTMLScriptElement;
  window.HTMLScriptElement = HTMLScriptElementOverride;

  /**
   * New `HTMLScriptElement` constructor.
   *
   * Allows us to globally override onload.
   * Not ideal to override stuff, but it helps with debugging.
   */

  function HTMLScriptElementOverride() {
    var script = new HTMLScriptElement;
    onnext(function(){ handleAsync(script); });
    return script;
  }
}

/**
 * Handle errors in events.
 *
 * @see http://stackoverflow.com/questions/951791/javascript-global-error-handling/31750604#31750604
 */

function handleEvents() {
  var addEventListenerx = window.EventTarget.prototype.addEventListener;
  window.EventTarget.prototype.addEventListener = addEventListener;
  var removeEventListenerx = window.EventTarget.prototype.removeEventListener;
  window.EventTarget.prototype.removeEventListener = removeEventListener;

  function addEventListener(event, handler, bubble) {
    var handlerx = wrap(handler);
    return addEventListenerx.call(this, event, handlerx, bubble);
  }

  function removeEventListener(event, handler, bubble) {
    handler = handler._witherror || handler;
    removeEventListenerx.call(this, event, handler, bubble);
  }

  function wrap(fn) {
    fn._witherror = witherror;

    function witherror() {
      try {
        fn.apply(this, arguments);
      } catch(e) {
        window.onanyerror.apply(this, e);
        throw e;
      }
    }
    return fn;
  }
}

/**
 * Handle image/ajax request errors generically.
 */

function handleAsync(obj) {
  var onerrorx = obj.onerror;
  obj.onerror = onerror;
  var onabortx = obj.onabort;
  obj.onabort = onabort;
  var onloadx = obj.onload;
  obj.onload = onload;

  /**
   * Handle `onerror`.
   */

  function onerror(error) {
    window.onanyerror.call(this, error);
    if (onerrorx) return onerrorx.apply(this, arguments);
  };

  /**
   * Handle `onabort`.
   */

  function onabort(error) {
    window.onanyerror.call(this, error);
    if (onabortx) return onabortx.apply(this, arguments);
  };

  /**
   * Handle `onload`.
   *
   * For images, you can get a 403 response error,
   * but this isn't triggered as a global on error.
   * This sort of standardizes it.
   *
   * "there is no way to get the HTTP status from a 
   * request made by an img tag in JavaScript."
   * @see http://stackoverflow.com/questions/8108636/how-to-get-http-status-code-of-img-tags/8108646#8108646
   */

  function onload(request) {
    if (request.status && request.status >= 400) {
      window.onanyerror.call(this, request);
    }
    if (onloadx) return onloadx.apply(this, arguments);
  }
}

/**
 * Generic error handler.
 *
 * This shows the basic implementation, 
 * which you could override in your app.
 */

function onanyerrorx(entity) {
  var display = entity;

  // ajax request
  if (entity instanceof XMLHttpRequest) {
    // 400: http://example.com/image.png
    display = entity.status + ' ' + entity.responseURL;
  } else if (entity instanceof Event) {
    // global window events, or image events
    var target = entity.currentTarget;
    display = target;
  } else {
    // not sure if there are others
  }

  capture(entity);
  console.log('[onanyerror]', display, entity);
}

/**
 * Capture stuff for debugging purposes.
 *
 * Keep them in memory so you can reference them
 * in the chrome debugger as `onanyerror0` up to `onanyerror99`.
 */

function capture(entity) {
  captures.push(entity);
  if (captures.length > 100) captures.unshift();

  // keep the last ones around
  var i = captures.length;
  while (--i) {
    var x = captures[i];
    window['onanyerror' + i] = x;
  }
}

/**
 * Wait til next code execution cycle as fast as possible.
 */

function onnext(fn) {
  setTimeout(fn, 0);
}

})();

Można go używać w ten sposób:

window.onanyerror = function(entity){
  console.log('some error', entity);
};

Pełny skrypt ma domyślną implementację, która próbuje wydrukować pół-czytelną "wyświetloną" wersję encji/błędu, który otrzymuje. Może być używany do inspiracji do obsługi błędów specyficznych dla aplikacji. Domyślna implementacja przechowuje również odniesienie do ostatnich 100 encji błędów, dzięki czemu można je sprawdzić w web console po wystąpieniu takich jak:

window.onanyerror0
window.onanyerror1
...
window.onanyerror99

Uwaga: działa to poprzez nadpisanie metod na kilku przeglądarkowych / natywnych konstruktorach. Może to mieć niezamierzone skutki uboczne. Jednakże, było to przydatne do użycia podczas rozwoju, aby dowiedzieć się, gdzie występują błędy, aby wysyłać dzienniki do usług takich jak NewRelic lub Sentry podczas rozwoju, abyśmy mogli mierzyć błędy podczas rozwoju, i na etapie, abyśmy mogli debugować, co się dzieje na głębszym poziomie. Można go następnie wyłączyć w produkcja.

Mam nadzieję, że to pomoże.
 11
Author: Lance Pollard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-16 12:29:45
// display error messages for a page, but never more than 3 errors
window.onerror = function(msg, url, line) {
if (onerror.num++ < onerror.max) {
alert("ERROR: " + msg + "\n" + url + ":" + line);
return true;
}
}
onerror.max = 3;
onerror.num = 0;
 6
Author: GibboK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-27 10:26:36

Należy również zachować wcześniej skojarzoną funkcję zwrotną OnError

<script type="text/javascript">

(function() {
    var errorCallback = window.onerror;
    window.onerror = function () {
        // handle error condition
        errorCallback && errorCallback.apply(this, arguments);
    };
})();

</script>
 5
Author: Apoorv Saxena,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-30 13:19:06

Polecam spróbować Trackjs .

To rejestrowanie błędów jako usługa.

Jest niezwykle prosty w konfiguracji. Wystarczy dodać jedną linię do każdej strony i to wszystko. Oznacza to również, że będzie to niezwykle proste do usunięcia, jeśli zdecydujesz, że ci się nie podoba.

Istnieją inne usługi, takie jakSentry (który jest open-source, jeśli możesz hostować własny serwer), ale nie robi tego, co robi Trackjs. Trackjs rejestruje interakcję użytkownika między przeglądarką i twój serwer WWW, dzięki czemu możesz rzeczywiście śledzić kroki użytkownika, które doprowadziły do błędu, w przeciwieństwie do tylko odwołania do pliku i numeru linii (i może śledzenia stosu).

 3
Author: kane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-16 12:22:50

Jeśli chcesz zunifikowany sposób na obsługę zarówno nieobsługiwanych błędów, jak i nieobsługiwanych odrzuceń obietnic, możesz zajrzeć do nieobsługiwanej biblioteki.

EDIT

<script type="text/javascript" src=".../uncaught/lib/index.js"></script>

<script type="text/javascript">
    uncaught.start();
    uncaught.addListener(function (error) {
        console.log('Uncaught error or rejection: ', error.message);
    });
</script>

Nasłuchuje okna.unhandledrejection oprócz window.onerror.

 3
Author: Aleksandr Oleynikov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-24 10:44:52

Nasłuchujesz zdarzenia onerror, przypisując funkcję do okna.onerror:

 window.onerror = function (msg, url, lineNo, columnNo, error) {
        var string = msg.toLowerCase();
        var substring = "script error";
        if (string.indexOf(substring) > -1){
            alert('Script Error: See Browser Console for Detail');
        } else {
            alert(msg, url, lineNo, columnNo, error);
        }   
      return false; 
  };
 1
Author: Ali Azhar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-07 09:37:50