【もりけん塾】JavaScript課題5 -DOM構築とPromiseオブジェクト①-

JavaScript

今日は、もりけん塾のJavaScript課題5 を終えて学んだことをアウトプットしていきます。

こんにちは。Webコーダーのはるです。

現在、所属している「もりけん塾」でハンズオン課題 に取り組み、レビューをいただいています。

今日は、課題5 についてアウトプットをしていきます。
(前回までのアウトプットは、こちらです。)

●課題5で学んだこと

・同期処理/ 非同期処理
・コールバック地獄
・Promiseの書き方
・Promiseが持つ3つのステータス

【もりけん塾】JavaScript課題5で学んだこと まとめ

今回、取り組んだ課題はこちらです。


(もりけん先生のJavaScriptハンズオン課題より)

同期処理/ 非同期処理

課題を始める前にPromiseについて調べることから始めました。

まず、MDNでPromiseを検索すると、

Promise オブジェクトは、非同期処理の完了 (もしくは失敗) の結果およびその結果の値を表します。

と出てきました。

非同期処理・・・?となったので調べました。

プログラムは上から下に順番に処理される。

同期処理の場合は、このルールに則り上から順番に処理を行う。
この場合、時間のかかる処理があると次の処理になかなか移れない問題が発生。
例えば、画像の読み込みが終わるまで他のコンテンツが読み込まれないなど。

そこで非同期処理があると、
時間のかかる処理の結果を待たずに、次の処理に進むことができる。
その間、時間のかかる処理はバックグラウンドで行われる。
結果が届いたら、中止していた元の処理を行う。

 

 

コールバック地獄

MDNと並行して「JavaScript本格入門」(書籍)を読んでいると「コールバック地獄」という単語が出てきました。よくわからなかったので掘り進めることにしました。

本を読むと、

  • 非同期処理を行うために古典的な方法としてコールバック関数がある
  • コードのネストが深く見にくすぎるコードになってしまので、コールバック地獄と呼ぶ

のだと知りました。

本の例をもっと簡潔に書くとこんな感じです。

first(function() {
    //処理
    second(function() {
        //firstが成功後の処理
        third(function() {
            //secondが成功後の処理
            fourth(function() {
                //thirdが成功後の処理
            });
        });
    });
});

firstから順に、関数の処理が成功したら次の関数..とするためにコールバック関数を使用すると、どんどんネストが深くなっていってしまいます。

コードがどんな処理を表しているのかパッと見てわかりにくい上に、デバックしにくく大きなバグを起こしやすくなるのだそうです。ほう。

このコールバック地獄を解決するために現れたのがPromiseです。

Promiseの存在にビクビクなのですが、救世主だったんですね😲

Promiseの書き方

次に、基本的はPromiseの書き方を勉強しました。

const 変数 = new Promise((resolve,reject) => {
    resolve(); //成功
    reject(); //失敗
}).then(() => {
}).catch(() => {
}).finally(() => {
});
  • new Promise とすることで、Promiseのインスタンスを作成。 => Promiseオブジェクト
const 変数 = new Promise()
  • Promiseの引数として、resolve・reject関数を指定
const 変数 = new Promise((resolve,reject) => 
  • 処理が成功→resolve, 処理が失敗→reject が実行される。
    関数の引数に取得したい値を入れることで、非同期処理の結果を格納できる。
resolve(); //成功
reject(); //失敗
  • さらに、then()メソッドをチェーンで使用することで、コールバック処理を行うことができる。
    then()は、promiseを返す。これは、resolve()で返ってきた値が引数に代入されるという意味。
.then(() => {
  • エラーハンドリングであるreject()の後に繋げたい処理は、then()も使用はできるが、catch()を使用してresolveと区別するとわかりやすい
.catch(() => {
  • 最後に、then()またはcatch()の後に実行されるのがfinally()
.finally(() => {

 

 

Promiseがもつ3つの状態

Promiseには3つのステータスがあり、常にどれかの状態にあります

① pending:初期状態
② fulfilled:処理成功→完了
③ rejected:処理失敗→完了
  • new PromiseでPromiseオブジェクトを作成した時点では、pending
  • resolve()が呼ばれた時は、fulfilled
  • reject()が呼ばれた時は、rejected

JavaScript課題5に挑戦

ここまで調べて、課題5に挑戦しました。もう一度課題を貼ります。

私の書いたコードは以下です。課題4のコードにPromiseの処理を追加しました。

const attributes = [
  { to: "bookmark.html", img: "1.png", alt: "画像1", text: "ブックマーク" },
  { to: "message.html", img: "2.png", alt: "画像2", text: "メッセージ" }
];

const ul = document.getElementById("js-lists");

const fragment = document.createDocumentFragment();

const promise = new Promise(resolve => {
  resolve(attributes);
}).then(attributes => {
  attributes.forEach(attribute => {
    const li = document.createElement("li");
    const anchor = document.createElement("a");
    const img = document.createElement("img");

    anchor.textContent = attribute.text;
    anchor.href = `/${attribute.to}`;
    img.src = attribute.img;
    img.alt = attribute.alt;

    li.appendChild(anchor).insertAdjacentElement("afterbegin", img);
    fragment.appendChild(li);
  });
  ul.appendChild(fragment);
});

今回はrejectの処理はないので、省略しました。

const promise = new Promise(resolve => {
  resolve(attributes);
}).then(attributes => {
アロー関数にやっと慣れてきたかなと思ったのですが、引数が一つの時は()を省略して書くことができるのですね…!知らないことばかりです。
せっかく知ったので、new Promise(resolve => というように使ってみました。
今回は、もりけん先生に課題を見ていただきこちらでApproveをいただきました。
ありがとうございます!
//

学習に使用している本は、もりけん先生推奨の”JavaScript本格入門”です。

あとがき

お忙しい時間を割いて課題を確認してくださったもりけん先生、ありがとうございました!

私の課題のリポジトリはこちらから確認できます↓

 

はじめてpromiseを使用したのですが、ここまでの理解にかなり時間がかかってしまいました。

まだ理解が十分とはいえないので、課題を進めつつしっかり調べていきたいと思います。

今日は以上です。

//

【もりけん塾で勉強しています】

もりけん先生(@terrace_tec)のHPはこちら