失敗を画面に出す
このレッスンで分かること
- コンソールに出しただけの失敗は、利用者から見れば起きていないのと同じです
- 受け止める場所を間違えると、失敗が成功のように見えてしまいます
コンソールに出した失敗は、利用者には見えない
前の 2 回で、失敗を受け止める書き方と、失敗の種類を自分で作る書き方をやりました。どちらも catch までは書けています。足りないのは、その先です。
JavaScript
try {
render(works);
} catch (error) {
console.log(error.message);
}これを書いた人は「エラー処理を書いた」と思っています。ですが利用者は開発者ツールを開きません。画面には何も出ず、押したボタンは反応せず、一覧は空のままです。利用者から見れば、失敗したのではなく壊れています。
出す文言は 3 つの問いに答えられていれば足ります。何が起きたのか、自分のせいなのか、次に何をすればよいのか。それ以上の詳細はコンソールに置きます。
受け止める場所を間違えると、失敗が成功に化ける
どこで受け止めるかは、間違えたときに何が起きるかを見ると決めやすくなります。まず、解析だけをする関数の中で受け止めて、空配列を返した場合です。
JavaScript
function parseWorks(text) {
try {
return JSON.parse(text);
} catch (error) {
return []; // 失敗が「0 件」に化ける
}
}呼ぶ側は 0 件を受け取り、画面に「まだ作品がありません」と出します。データが途中で切れているのに、利用者には正常な空の状態に見えます。問い合わせも来ないので、誰も気づきません。
反対に、一番外側で 1 回だけ受け止めるとこうなります。
JavaScript
try {
drawHeader();
drawWorks();
drawContactForm();
} catch (error) {
showNotice("読み込みに失敗しました");
}作品の解析が失敗すると、その下のフォームの描画まで動きません。作品が出ないだけで済むはずが、問い合わせもできない画面になります。
受け止めるのは、失敗したときに画面をどうするか知っている場所です。解析する関数は、赤い枠を出すべきかどうかを知りません。同じ関数を別の画面から呼ぶかもしれないからです。だからそこでは受け止めず、その画面を組み立てている関数の側で受け止めます。
出した表示は、次の読み込みで消す
表示の出し入れは、style.display を JavaScript から書き換えるのではなく、class の付け外しで行います。見た目の指定が CSS と JavaScript に分かれると、あとから配色を変える人がどちらを直せばよいか分からなくなります。
CSS
.notice { display: none; }
.notice.is-shown { display: block; }JavaScript
panel.textContent = "作品を読み込めませんでした (" + error.name + ")";
panel.classList.add("is-shown");error.message をそのまま出すと、利用者に「Unexpected end of JSON input」と見せることになります。伝わらないうえ、環境によって文面が変わります。出すのは自分で決めた 1 文にして、問い合わせを受けたときの手がかりとして error.name だけを添えます。
そして忘れやすいのが、消すほうです。
| する場所 | すること |
|---|---|
| 読み込みの開始時 | 前の失敗の表示を消す |
| 成功したとき | 一覧を描き直す |
| 失敗したとき | 理由を出し、一覧を空にする |
消し忘れると、正しいデータを読み直して作品が並んでいるのに、上には失敗の文言が残ったままになります。消す処理を開始時の 1 か所にまとめておけば、これから読み込みの入口が増えても書き足す必要がありません。
よくある間違い
- 失敗を
alertで出す — 押すまで消えず、押したら跡が残りません。利用者は文言を読み返せず、画面のどこが失敗したのかも分かりません。失敗した場所の近くに、消えない形で出します - 隠すつもりで要素を消す —
panel.remove()で見えなくはなりますが、次に失敗したときに出す先が無くなります。隠すのと消すのは違います。付け外しするのは class だけにします
課題
- showError(message) で #error-panel に文を入れ、is-error を付ける。一覧は空にして #work-list に is-empty を付ける
- clearError() で #error-panel の文を消し、is-error と is-empty を外す
- showWorks(kind) は最初に clearError() を呼び、try の中で loadWorksText(kind) の文字列を JSON.parse する
- 解析した結果が配列でなければ自分で throw し、catch で showError を呼ぶ
- 画面に出す文言は「作品を読み込めませんでした」で始め、括弧の中に error.name を添える