Došlo k chybě ve skriptu

facepalm 80

Omlouváme se, ale článek, který na serveru hledáte, tu pravděpodobně není. Možná ho někdo smazal, možná tu nikdy nebyl, možná jste se uklepli v adrese. Server možná ztratil spojení s databází. Máte nepodporovaný prohlížeč. Došlo k obecné chybě. Omlouváme se. Zkuste to za chvíli znovu… Co s tím uděláme?

Ohlásit chybu uživateli je složité.

Myslíte, že není? Že není nic snazšího než napsat „Chyba: dělení nulou na adrese 0×00053AFD“? Ale to je něco jiného. To není hlášení chyby, to je diagnóza. Dokonce i napsat „Ouha, něco se pokazilo, zkuste to za chvíli“ je lepší než tohle. Chybové hlášení, které uživatele zmate, je mnohem horší než takové, které mu neřekne nic.

K tomu, aby chybové hlášení fungovalo, je zapotřebí dvou věcí.

Za prvé: přiznat si, že mohu udělat chybu. Udělat chybu není životní prohra, nemusíte se proto tvářit, že jste ji neudělali a snažit se ji zamaskovat. Vývojářské pravidlo říká „zhavarujte rychle!“ Pokud je evidentní, že jste něco pokazili, neošetřili, zmotali, nešlapte v tom a raději to rychle opravte. Uživatelům se omluvíte, oni to pochopí a nikdo vás nebude topit na lžíci vody, protože (snad kromě některých komentátorů) děláme chyby všichni. Přiznat chybu, napravit ji, omluvit se.


motifake.com

Udělali jste chybu… Víte, co to znamená…

Za druhé: Musím se o chybě dozvědět a mít způsob, jak ji zpracovat.

Jak hlásit chyby?

Důležitý moment je vědět, že uživatel a vývojář potřebují v případě chyby zcela rozdílné informace. Vývojář potřebuje záznamy, výpisy, místo havárie… Uživatel to vědět nepotřebuje, ale potřebuje být ujištěn, že se opravdu stalo něco špatně, a co má dělat.

Pokud chyba vznikla v důsledku nějaké uživatelovy činnosti, jako že udělal něco, co udělat neměl, zmáčkl něco, co zmáčknout neměl, napsal něco špatně a tak, je na místě být v chybovém hlášení jasný a přesný: „Zadal jste špatně číslo, zadejte ho takto…“, „Musíte zaškrtnout jednu z možností“, „Na toto tlačítko, prosím, už nikdy neklikejte, pokud chcete, aby váš kocour přežil“ a podobně. Uživatelovy chyby se dají většinou dobře identifikovat a zachytit. Ale co chyby systému, nebo dokonce chyby v kódu? (Ne nutně ve vašem…)

Na straně serveru je to o něco jednodušší. Můžete si logovat neobvyklé stavy, můžete si podrobně diagnostikovat problémy a uživatelům sdělíte jen to, že se stalo něco špatně a že to napravíte. Ovšem na straně klienta je to obtížnější.

Klient má prohlížeč, v něm mu běží JavaScript, a ten má k chybám poměrně zvláštní postoj: mlčí. Donedávna si člověk všiml chyby v JavaScriptu jen když se díval, jestli tam nějaká nebyla, a když už se o ní dozvěděl, tak na ni leckdy nevěřícně koukal (známé „null má hodnotu null nebo není objekt. Řádka: 12, Znak 1182, Kód: 0“). Vývojáři mají k dispozici chybové konzole a dozvědí se (dnes už…) víc, ale uživatel?

Uživatel vidí chybu v JavaScriptu jako mysteriózní změnu chování, pro kterou není „zjevný“ důvod. Vše funguje až do určité chvíle, kdy například na něco klikne, nebo načte víc záznamů, a najednou přestanou některé funkce pracovat. Třeba už se nenačítají nové hodnoty. Přestane fungovat psaní. Nelze odeslat formulář. Nemůže kliknout na položku v menu. Stránka se celá rozsype. (Mezi nejmysterióznější chyby patří parse errors, které ukončí vykonávání skriptů vůbec, a uživatel nemá naprosto tušení, proč stránka, co ještě včera fungovala, najednou sice je vidět, ale nepracuje.)

Syntaktické apod. chyby totiž nevypíšou velké blikající „Něco je špatně, uživateli, kontaktuj administrátora!“, ale bez varování ukončí provádění skriptů (nebo způsobí ještě něco jiného) a nedají to nijak najevo. Vývojář se o tom z logu nedozví a zjistí to až z naštvaných mailů od uživatelů. A co si budeme povídat – většinou se dozví variaci na „Máte to rozbitý“.

Řešením by mohlo být zavírání celých skriptů do velkých bloků try…catch, ale chybí tomu jednak elegance, jednak to neřeší problém např. při načítání skriptů z jiných domén nebo skriptů bez tohoto „řešení“, a v neposlední řadě to je „ad hoc“ přístup, chybí mu univerzálnost.

window.onerror

V prohlížečích je možnost zachytit událost window.onerror, která je vyvolána při chybě – syntaktické, běhové, při neošetřené výjimce apod.

Podpora v prohlížečích je silně nevyvážená: IE tuto konstrukci podporuje od verze 5.5 (!), FF od verze 6, Chrome od verze 13, Safari od 5.1 a Opera od verze 11.60. Nelze to tedy nazvat jednoznačně „novinkou“.

Obsluha je jednoduchá. Systém předá obslužné funkci tři parametry: chybové hlášení, URL skriptu, ve kterém došlo k chybě, a číslo řádku.

window.onerror = function(message, url, line) {
  alert("Chyba: " + message + " na řádku " + line + " ve skriptu " + url);
}

Je (logicky) třeba, aby nastavení chybové obsluhy proběhlo dřív než samotná chyba. Tedy (pokud možno) v prvním načteném skriptu.

Obsluhu můžete nastavit i pro element <body>, podobně jako se nastavuje  onload:

<body onerror="alert('Chyba: ' + event + ' na řádku ' + lineno + ' ve skriptu ' + source)">

Co s chybou?

<nadsázka> Můžete ji zamlčet. Vy totiž chyby neděláte, a kdyby se vinou nedokonalé techniky do kódu dostala, tak se o tom nikdo nesmí dozvědět, tím míň neznalý uživatel – mohl by si pak myslet o autorovi bůhvíco! (To si bude myslet stejně…) </nadsázka>

window.onerror = function(){return false;}

 „Blikala nám tam kontrolka PORUCHA. Tak jsme ji přelepili a od té doby nemáme žádné poruchy hlášené…“ Za chybu vám nikdo hlavu neutrhne. Za tohle by se ale trhat měly!

Rozumný přístup je, samozřejmě, ten věcnější. Chybu můžete zachytit, můžete sdělit uživateli, že je něco špatně, upozornit ho, že za to nemůže on (a ani několikeré zmáčknutí F5 nepomůže), omluvit se, samozřejmě – a taky si můžete nechat poslat to hlášení, aby vám k něčemu bylo:

window.onerror = function(message, url, line) {
  if (window.XMLHttpRequest) {

    var xhr = new XMLHttpRequest();
    var logurl = "http://www.example.com/errorlog";
    var log = message + "n" + url + "n" + line;
    xhr.open("POST", logurl);
    xhr.setRequestHeader("Content-Type", "text/plain");
    xhr.send(log);
  }
  return false;
}

Případná syntaktická nebo běhová chyba nezpůsobí „zaseknutí“ celého JS engine (což vždy znamená „záhadné“ chyby a zmateného uživatele, který neví, co má dělat). Systém ji dokáže zachytit a zpracovat – tedy například takto poslat potřebné informace vývojáři. Pak už je třeba jen vhodně zareagovat a důstojně zhavarovat.

Důstojně zvládnout chybu je vždy to nejlepší možné řešení. A to platí nejen pro JavaScript.

Začal programovat v roce 1984 s programovatelnou kalkulačkou. Pokračoval k BASICu, assembleru Z80, Forthu, Pascalu, Céčku, dalším assemblerům, před časem v PHP a teď je rád, že neprogramuje…

Čtení na léto

Jaké knihy z oboru plánujete přečíst během léta? Pochlubte se ostatním ve čtenářské skupině Zdrojak.cz na Goodreads.com.

Komentáře: 13

Přehled komentářů

srigi Riesenie try/catch v JS
Oldisy3 Tak jako obcas kritizuji
Ajax Dekuji
Gappa Firefox vs onerror a problém s cizími chybami
nothrem Re: Firefox vs onerror a problém s cizími chybami
Gappa Re: Firefox vs onerror a problém s cizími chybami
Čtenář Úsměvné
Martin Malý Re: Úsměvné
Laethnes Re: Úsměvné
Audiod Rozumné oznámení chyby
windowsupdate Re: Rozumné oznámení chyby
Tom Super článek
Ivan Novakov Chyba v onerror callbacku
Zdroj: http://www.zdrojak.cz/?p=3599