もりけん塾 JavaScript課題5 Promiseを使って、解決された値を取得する

もりけん塾 JavaScript課題5 Promiseを使って、解決された値を取得する

お題

前回の配列を使うのは一緒です。

4のこちらをつかって、こんどはPromiseオブジェクトを使って解決された値として受け取り、

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

同じように

<ul>
 <li><a href="/bookmark.html"><img src="1.png" alt="画像1">ブックマーク</a></li>
 <li><a href="/message.html"><img src="2.png" alt="画像2">メッセージ</a></li>
</ul>

こちらの出力になるようにしてください

準備

そもそもPromiseとは。解決された値とは。何でしょうか。問題の意味さえ、さっぱりわからないので、とりあえずPromiseについて調べます。

Promiseとは、非同期処理を扱いやすくするものらしいです。調べても、さっぱりわかりません。とりあえず、色々な記事を何回も繰り返し読んでみます。

Promiseについてわかりやすかった記事を紹介します。Promiseをどうやって使うのかよりもPromiseって一体何?というのを、スターウォーズに例えて、わかりやすく説明してくれており、少し理解することができました。

どうして非同期処理が必要なのか?

JavaScriptは、コードの上から順番に処理されていきます。そうすると、上の処理が終わるまで次の処理を待たないといけません。非同期処理とは、1つの処理が終了するのを待たずに、次の処理を実行することです。

ファイルの読み込みや、データベースへのアクセスなど非同期処理で行うことが多いそうです。

サーバーへの通信が必要な時に、サーバーへアクセスするのに時間がかかったりする場合、その処理を待っていないといけないとすると、ユーザーは長い時間待っていないといけなかったりするので、問題になります。

非同期処理をすると全体の処理速度を早めることが可能なので、応答性、操作性がよくなるというメリットがあります。

一方で、複雑になりやすいので、わかりやすい記述や設計をすることが大切のようです。

同期処理、非同期処理についてはこちらの記事がわかりやすかったです。

https://www.rworks.jp/system/system-column/sys-entry/21730/

最初の回答

とりあえずコードを書いてみます。解決されているというのが、どういうことなのかよくわからないです。出力はされているので、こちらでプルリクエストしました。

const promise = new Promise(resolve => {
    resolve(lists)
});

promise.then(() => {
    const fragment = document.createDocumentFragment();
    for(const list of lists){
        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).insertAdjacentElement('afterbegin',img);
    }
    ul.appendChild(fragment);
});

resolve(lists)の後に、; をつけ忘れたり、promise.then()の変数がない、ループ処理の参照している値が違う、a.href = '/' +list.to;はテンプレートリテラルを使った方がいいというレビュー頂きました。自分でも何がしたいのかわからなくなり、もう一度Promiseについて調べました。

修正したコード

const ul = document.getElementById('js-list');
const lists = [
    {to: "bookmark.html", img: "1.png", alt:"画像1", text: "ブックマーク"},
    {to: "message.html", img: "2.png", alt:"画像2", text: "メッセージ"}
   ]

const promise = new Promise(resolve => {
    resolve(lists);
});

promise.then((lists) => {
    const fragment = document.createDocumentFragment();
    for(const list of lists){
        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).insertAdjacentElement('afterbegin',img);
    }
    ul.appendChild(fragment);
});

こちらで再度プルリクエスト!

しかしこのコードだと、ループで回している箇所は、最初のconst listsを参照していることになる、とレビューをもらいました。Promiseで解決された値をループさせる必要があるので、再度修正。

うーん、難しい。。よく考えて、promise.then((lists) => { promise.then((value) => { に変更しました。ちゃんと解決された値を受け取っているのか、console.log(value);でvalueに格納された値を取得してみることにしました!

const ul = document.getElementById('js-list');
const lists = [
    {to: "bookmark.html", img: "1.png", alt:"画像1", text: "ブックマーク"},
    {to: "message.html", img: "2.png", alt:"画像2", text: "メッセージ"}
   ]

const promise = new Promise(resolve => {
    resolve(lists);
});

promise.then((value) => {
    const fragment = document.createDocumentFragment();
    console.log(value);
    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).insertAdjacentElement('afterbegin',img);
    }
    ul.appendChild(fragment);
});
console.log(value);

コンソールで出力された値をみてみると、下記のようになっていました。無事にvalueに解決された値を渡すことができたようです。

0: {to: 'bookmark.html', img: '1.png', alt: '画像1', text: 'ブックマーク'}
1: {to: 'message.html', img: '2.png', alt: '画像2', text: 'メッセージ'}
length: 2

最終的なコード

const ul = document.getElementById('js-list');
const lists = [
    {to: "bookmark.html", img: "1.png", alt:"画像1", text: "ブックマーク"},
    {to: "message.html", img: "2.png", alt:"画像2", text: "メッセージ"}
   ]

const promise = new Promise(resolve => {
    resolve(lists);
});

promise.then((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).insertAdjacentElement('afterbegin',img);
    }
    ul.appendChild(fragment);
});

無事に、こちらでapprove頂くことができました!すっごく理解が難しかったので、とても嬉しかったです!

今回学んだこと

  • Promiseのresolveの使い方
  • Promiseの非同期処理について
  • console.log();の使い方

Promiseの使い方については、まだしっかり理解しきれていないので、次の課題を進めながら、復習したいと思います。

次の課題はこちら

私が所属しているフロントエンドエンジニアを目指す方のための塾 「もりけん塾」の森田賢二先生のTwitterはこちら!

先生のブログ「武骨日記」はこちら!

https://kenjimorita.jp/

まい

Webサービス制作会社で、Wordpressのテーマ開発や2Dシミュレーターの開発、JavaScriptを使用したフロントエンド周りの実装を担当しています。 JavaScriptが好きです。 最近は、3D Model Configuratorの制作にチャレンジしています。

もりけん塾カテゴリの最新記事