Disassembler

Artificial intelligence is no match for natural stupidity.
28prosince2011

Reportování client-side chyb JavaScriptu


Optimalizace JavaScriptu pro všechny majoritní prohlížeče je občas pořádný očistec. A i když už máte optimalizováno, stejně se tu a tam může vyskytnout nějaká méně očividná moucha. Pokud váš projekt neprochází žádnou hlubokou analýzou kvality, můžete si s reportováním chyb pomoci sami. Potřebujete k tomu AJAX, metodu window.onerror a nějaký PHP skript, který bude zaslané reporty zpracovávat a ukládat.

Pojídač chyb


Metoda window.onerror je, jak název napovídá, handler chytající všechny chyby. V parametrech předává chybovou hlášku, jméno souboru nebo skriptu, ve kterém se chyba vyskytla a číslo řádku.

window.onerror = function (msg, url, line) {
    // tělo funkce
}

V kombinaci s AJAXem tedy můžete tyto informace o chybě zachytit a poslat zpět na server, kde snadno uvidíte kolik klientů má s jakou JavaScriptovou součástí problém.

Plný skript by pak mohl vypadat nějak takto

function XHR() {
    try {
        return new XMLHttpRequest();
    } catch (e) {}
    try {
        return new ActiveXObject('Msxml2.XMLHTTP.6.0');
    } catch (e) {}
    try {
        return new ActiveXObject('Msxml2.XMLHTTP.3.0');
    } catch (e) {}
    try {
        return new ActiveXObject('Msxml2.XMLHTTP');
    } catch (e) {}
    return false;
}

window.onerror = function (msg, url, line) {
    var xhr = new XHR();
    if (xhr === false)
        return true;
    var params = 'msg='+encodeURIComponent(msg)+'&url='+encodeURIComponent(url)+'&line='+encodeURIComponent(line);
    xhr.open('POST', 'errorlogger.php', true);
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.setRequestHeader('Content-length', params.length);
    xhr.setRequestHeader('Connection', 'close');
    xhr.send(params);
    return true;
}

Do samotné stránky se vkládá stejně jako jakýkoliv jiný slušný skript (tedy do hlavičky)

<html>
    <head>
        <title>Title</title>
        <script type="text/javascript" src="errorlogger.js"></script>
    </head>
    <body>
        <div>
            Obsah stránky
        </div>
        <script type="text/javascript">
            chyba();
        </script>
    </body>
</html>

Jednoduchý server-side skript pro ukládání do souboru může vypadat třeba takto

<?php
if (isset($_POST['msg'], $_POST['url'], $_POST['line'])) {
    $errorline = $_SERVER['REMOTE_ADDR'].' reported JS error "'.$_POST['msg'].'" in file "'.$_POST['url'].'" on line '.$_POST['line'];
    file_put_contents('errorlogger.log', $errorline, FILE_APPEND | LOCK_EX);
}
?>

A voila. Do souboru errorlogger.log výše uvedený skript uloží například

123.45.67.89 reported JS error "Uncaught exception: ReferenceError: Undefined variable: chyba" in file "http://www.example.com/errorlogger.htm" on line 2

jQueryisti si pak můžou ulehčit práci a skript zredukovat na

window.onerror = function (msg, url, line) {
    $.post('errorlogger.php', { msg: msg, url: url, line: line });
}

Bohužel kvůli bugu v jQuery není možno spolehlivě použít

$(window).error()

Nakonec bych ještě rád podotkl, že metoda onerror nemusí sbírat pouze chyby skriptů, ale i jiné, jak uvádí tato tabulka na QuirksMode.org. Výše uvedená trojice skriptů byla úspěšně otestována v prohlížečích Firefox 7.0.1, Chrome 15, IE 9 a Opera 11.60.