課題8はPromiseのエラーの処理を実装します。
お題
つぎはresolveで解決するのではなく(resolveを実行するのではなく) 3秒後にrejectを実行してthenでその値をコンソール出力してください。ローディングはぐるぐる状態で良いです。
いままでresolveとしていたところでrejectを実行して、エラーを起こしてcatch節でエラーをキャッチしてください
準備
resolveは非同期処理の成功を示し、thenの引数の処理を実行します。rejectは失敗を示し、catchの引数の処理を実行します。
最初のコード
今回は、senさんとにゃっつさんにコードレビューをして頂きました。いつも本当にありがとうございます!
function createLoading(){
const loadingImg = document.createElement('img');
loadingImg.src = "loading-circle.gif";
loadingImg.alt = "ローディング画像";
document.getElementById('js-loading').appendChild(loadingImg);
}
function removeLoading(){
document.getElementById('js-loading').remove();
}
function createList(value){
const fragment = document.createDocumentFragment();
for(const list of value){
const li = document.createElement('li');
const a = document.createElement('a');
const img = document.createElement('img');
a.textContent = list.text;
a.href = `/${list.to}`;
img.src = list.img;
img.alt = list.alt;
fragment.appendChild(li).appendChild(a).appendChild(img);
}
document.getElementById('js-list').appendChild(fragment);
}
function getList(){
createLoading();
return new Promise((resolve,reject) => {
const lists = [
{to: "bookmark.html", img: "1.png", alt:"画像1", text: "ブックマーク"},
{to: "message.html", img: "2.png", alt:"画像2", text: "メッセージ"}
];
setTimeout(() => reject(Error('エラーです')),3000);
});
}
getList().then((value) =>{
removeLoading();
createList(value);
})
.catch((error) => {
console.error(error);
});
前回の課題の際には、document.getElementById(‘js-loading’)を一旦、変数に格納していました。しかし、この関数の中で繰り返し使う変数ではないため、変数宣言はやめて処理の最後に要素の取得をまとめました。わずかですが、コードを短くすることができるので、そうしました。
前回のコード↓
function createLoading(){
const ul = document.getElementById('js-loading');
const loadingImg = document.createElement('img');
loadingImg.src = "loading-circle.gif";
loadingImg.alt = "ローディング画像";
ul.appendChild(loadingImg);
}
今回のdocument.getElementById(‘js-loading’)を変数に格納するのをやめたコード↓
function createLoading(){
const loadingImg = document.createElement('img');
loadingImg.src = "loading-circle.gif";
loadingImg.alt = "ローディング画像";
document.getElementById('js-loading').appendChild(loadingImg);
}
同様の理由で関数createList(value)の中で、document.getElementById(‘js-list’)を変数に格納するのをやめました。
function createList(value){
const fragment = document.createDocumentFragment();
for(const list of value){
const li = document.createElement('li');
const a = document.createElement('a');
const img = document.createElement('img');
a.textContent = list.text;
a.href = `/${list.to}`;
img.src = list.img;
img.alt = list.alt;
fragment.appendChild(li).appendChild(a).appendChild(img);
}
document.getElementById('js-list').appendChild(fragment);
}
getList()という関数の中に、取得するlistのデータが入っているのは違和感なので、const listsは関数の外で宣言した方がいいかも、とコメントを頂きました。
function getList(){
createLoading();
return new Promise((resolve,reject) => {
const lists = [
{to: "bookmark.html", img: "1.png", alt:"画像1", text: "ブックマーク"},
{to: "message.html", img: "2.png", alt:"画像2", text: "メッセージ"}
];
setTimeout(() => reject(Error('エラーです')),3000);
});
}
const listsについては、スコープや可読性を考えると、関数の中で宣言するのが適切と思い、関数名を変えることにしました。(エラー起こすために、listsのデータはこの課題では取得していないですが、この後の課題で使います。)
関数の中でやっていることが伝わっていないので、適切ではないと思ったからです。
変数名、関数名の付け方の適切な方法がわからず、色々調べました。変数名は基本的に名詞、関数名は目的語+動詞にするということがわかりました。
英語ができないからって横着せずに、ちゃんと意味のわかる関数名をつけよう、という記事を見かけ、頭から水をかけられたような感覚に。自分が関数名をなるべくシンプルにしようとしていたのは、具体的に何をしている処理なのかを考えるのから逃げていたのかも、と思い知った感じでした。
また、コードを単純に読みやすくするためには、インデントを揃える、一貫性のあるコードを書く、マジックナンバーを書かない、などの基本的なことを当たり前にやろうというのを学びました。
関数名をつけるときに役立つサイト:
記述を少なくシンプルにすることが可読性高くていい、と思っていたのですが、記述が短くても、意味が伝わらなければそれは理解に時間がかかるコードになります。記述が単に少ないことが読みやすい(理解しやすい)コードというわけではないということを知りました。処理の内容や意味が伝わる具体的な関数名をつけよう、という考えが腑に落ちました。
もりけん先生は、スコープによりitemなどのシンプルな命名はあり&ベストプラクティスは言語により異なるとの見解でした。
「リーダブルコード」という本を読んでみることをおすすめして頂いたので、早速、某通販サイトで注文しました。誰にでも伝わりやすいコードをかけるようになりたいです。
最終的なコードはこちらです。もう少し関数名を改善する余地がありそうです。
function createLoading(){
const loadingImg = document.createElement('img');
loadingImg.src = "loading-circle.gif";
loadingImg.alt = "ローディング画像";
document.getElementById('js-loading').appendChild(loadingImg);
}
function removeLoading(){
document.getElementById('js-loading').remove();
}
function createLists(value){
const fragment = document.createDocumentFragment();
for(const list of value){
const li = document.createElement('li');
const a = document.createElement('a');
const img = document.createElement('img');
a.textContent = list.text;
a.href = `/${list.to}`;
img.src = list.img;
img.alt = list.alt;
fragment.appendChild(li).appendChild(a).appendChild(img);
}
document.getElementById('js-list').appendChild(fragment);
}
function SetDataToLists(){
createLoading();
return new Promise((resolve,reject) => {
const lists = [
{to: "bookmark.html", img: "1.png", alt:"画像1", text: "ブックマーク"},
{to: "message.html", img: "2.png", alt:"画像2", text: "メッセージ"}
];
setTimeout(() => reject(Error('エラーです')),3000);
});
}
SetDataToLists().then((value) =>{
removeLoading();
createLists(value);
})
.catch((error) => {
console.error(error);
});
参考にした記事:
今回学んだこと
- Promiseのエラー処理について
- 変数名、関数名の命名規則について
- 読みやすいコード理解しやすいコードの書き方について
コードを書く前に、学ぶべきことがたくさんあるな、ということに気づけたので、とてもいい経験になりました。
私が所属しているフロントエンドエンジニアを目指す方のための塾 「もりけん塾」の森田賢二先生のTwitterはこちら!
【募集】フロントエンド、とりわけJavaScriptを教えてもらいたい塾生を募集しています。条件はありますが、お金は頂きません。詳しくはDMください#JavaScript教えてもらいたい方#駆け出しのエンジニアと繋がりたい
— フロントエンドエンジニア (@terrace_tech) April 18, 2020
わたしについて👉https://t.co/FETVmMT5AY
先生のブログ「武骨日記」はこちら!