今日は、もりけん塾のJavaScript課題10 を終えて学んだことをアウトプットしていきます。
こんにちは。Webコーダーのはるです。
現在、所属している「もりけん塾」でハンズオン課題 に取り組み、レビューをいただいています。
今日は、課題10 についてアウトプットをしていきます。
(前回までのアウトプットは、こちらです。)
●課題10で学んだこと
・適切な関数名について
【もりけん塾】JavaScript課題10で学んだこと まとめ
今回、取り組んだ課題はこちらです。
(もりけん先生のJavaScriptハンズオン課題より)
課題9ではPromiseのasync/awaitを使用したloadingの実装をしました。
同じコードにtry,catch,finallyを追加していきます。
try,catch,finallyについて
try {
//例外が起こりうる処理
}
catch {
//例外が発生した際の処理
}
finally {
//例外の有無に関係なく最後に行われる処理
}
最初にPRしたコードはこちらです。
const ul = document.getElementById("js-lists");
const attributes = [
{ to: "bookmark.html", img: "1.png", alt: "画像1", text: "ブックマーク" },
{ to: "message.html", img: "2.png", alt: "画像2", text: "メッセージ" }
];
function addLoading() {
const li = document.createElement("li");
const img = document.createElement("img");
li.id = "js-loading";
img.src = "loading-circle.gif";
ul.appendChild(li).appendChild(img);
};
function removeLoading() {
const li = document.getElementById("js-loading");
ul.removeChild(li);
};
function fetchListData() {
addLoading();
return new Promise(resolve => {
setTimeout(() => resolve(attributes), 3000);
});
};
function handlingException() {
try {
fetchListData();
} catch {
const error = 'エラー:データが取得できません';
console.error(error);
} finally {
removeLoading();
}
};
handlingException();
async function addList() {
const fragment = document.createDocumentFragment();
const values = await fetchListData();
removeLoading();
values.forEach(value => {
const li = document.createElement("li");
const anchor = document.createElement("a");
const img = document.createElement("img");
anchor.textContent = value.text;
anchor.href = `/${value.to}`;
img.src = value.img;
img.alt = value.alt;
li.appendChild(anchor).insertAdjacentElement("afterbegin", img);
fragment.appendChild(li);
});
ul.appendChild(fragment);
};
addList();
レビュー①:エラーがcatchできていない
function handlingException() {
try {
fetchListData();
} catch {
const error = 'エラー:データが取得できません';
console.error(error);
} finally {
removeLoading();
}
};
handlingException();
もりけん先生(@terrace_tec)が、そのことをとてもわかりやすくレビューしてくださいました。
わかりやすいのは、
handlingExceptionの定義と実行をコメントアウトしてから、
function fetchListData() {
addLoading();
a // add
return new Promise(resolve => {
setTimeout(() => resolve(attributes), 3000);
});
};
このようにするとaを書くと当然aは未定義なのでエラーですが
Uncaught (in promise) ReferenceError: a is not defined
それをキャッチできていません。
前述のように実際はhandlingExceptionは何もしていないので
addList内のfetchListDataに対して施さなくてはいけないです
fetchListDataにエラーが起きた時、そのエラーを取得できるようにコードを考えました。
async function handlingException() {
try {
return await fetchListData();
} catch(e) {
console.error(e.message);
} finally {
removeLoading();
}
};
async function addList() {
const fragment = document.createDocumentFragment();
const values = await handlingException();
(以下略)
fetchListData()をawaitして→最後のaddList()でhandlingException()をawaitするコードに変更しました。
先程のように、
function fetchListData() {
addLoading();
a // add
return new Promise(resolve => {
setTimeout(() => resolve(attributes), 3000);
});
};
a を追加してみると、’a is not defined’というエラー文を出力することができました。きちんとcatchできています。
レビュー②:removeLoadingの重複
塾生のsenさん(websen5)にレビューをいただきました!
今回、新しくtry,catch,finally文の中でremoveLoading()関数を呼び出しました。
async function handlingException() { try { return await fetchListData(); } catch(e) { console.error(e.message); } finally { removeLoading(); } };
finallyに書いた処理は、例外が発生しても発生しなくても最後に必ず行われるため、addList()関数内にあるremoveLoading();は不要であることに気付けました。
ありがとうございます!
レビュー③:関数名について
もりけん先生(@terrace_tec)にレビューをいただきました。
とても大切だと思ったので、先生がまとめてくださった部分を引用します。
-名前は実行順にコードを読んでいて「ん?」とならないようにする
-名前は仕事をする内容を書く。名前以外の仕事はしない
-実行する関数から得られる値の名前が不自然じゃないか気を配る
-抽象的な名前か具体的な名前にするべきかちょっと考えてみる
handlingException() = 除外をhandling する関数
なのに、その中でfetchListData()を実行しているのに違和感がある…
確かに…
function handlingException() {
try {
fetchListData();
} catch {
const error = 'エラー:データが取得できません';
console.error(error);
} finally {
removeLoading();
}
};
fetchListDataした結果で除外handlingする方が流れがわかりやすい。
さらに、fetchListData()はもっと抽象的な名前であるべき = データを返すだけの関数であるべき
ことからfetchData()という抽象的な名前かつ、addLoading()もtry,catchの書かれている呼び出し元に移動するというコードを先生に書いていただきました😭✨
function fetchData() {
return new Promise(resolve => {
setTimeout(() => resolve(attributes), 3000);
});
};
async function fetchListData() {
addLoading();
try {
return await fetchData();
} catch(e) {
console.error(e.message);
} finally {
removeLoading();
}
};
async function addList() {
const fragment = document.createDocumentFragment();
const values = await fetchListData();
関数名も自然な流れになり、関数の中も関数名に合った処理のみになりました。
勉強になりました。ありがとうございます!
//
学習に使用している本は、もりけん先生推奨の”JavaScript本格入門”です。
あとがき
お忙しい時間を割いて課題を確認してくださったもりけん先生(@terrace_tec)・塾生のsenさん(websen5)ありがとうございました!!
私の課題のリポジトリはこちらから確認できます↓
今日は以上です。
//
【もりけん塾で勉強しています】
もりけん先生(@terrace_tec)のHPはこちら