【もりけん塾】JavaScript課題9 -ローディング実装 ③ async/await –

JavaScript

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

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

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

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

●課題9で学んだこと

・Promiseのasync/awaitについて
・Promiseのインスタンス作成の書き方

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

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

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

課題7ではPromiseを使用してloadingの実装をしました。

同じコードを使用して、async/awaitを使った実装に変更してみます!

Promiseのasync/awaitについて

async/await を使用するのは初めてだったので、調べるところから始まりました。

asyncとは?

まず、MDNで調べました。

AsyncFunction コンストラクターは、新しい非同期関数オブジェクトを生成します。 JavaScript では、すべての非同期関数が実際に AsyncFunction オブジェクトです。

非同期関数オブジェクトを生成する…?となったのでさらに読み進める

非同期関数は async キーワードで宣言され、その中で await キーワードを使うことができます。 async および await キーワードを使用することで、プロミスベースの非同期の動作を、プロミスチェーンを明示的に構成する必要なく、よりすっきりとした方法で書くことができます。

プロミスチェーンで書くよりも、async/awaitを用いると読みやすくなるらしいことがわかった。

ここまで読んでハテナが残ったので、Promiseの本なるものを読みました。

 Async Functionは通常の関数とは異なり、必ずPromiseインスタンスを返す関数を定義する構文です。

Async Functionではreturnした値の代わりに、Promise.resolve(返り値)のように返り値をラップしたPromiseインスタンスを返します。

関数名の前にasyncをつけることによって、Promiseインスタンスを返す…

この部分がしっくりこなかったので、課題のコードの関数addList()にasyncをつけて、console.logしてみました。function内には明示的にpromiseがなかったものの、コンソールでpromiseが返ってきていることが確認できました。

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);
};

console.log(addList());

async functionはpromiseを返し、その値をresolveかrejectするということも学習しました。

明示的にpromiseが書かれていなくてもpromiseを返す&resolveかrejectするということは…

async function test() {
  return "これはresolveされているか確認するtestです"
}

test().then(value => {
  console.log(value); //これはresolveされているか確認するtestです
})

このように、asyncのついたfunctionにthenのチェーンを繋げると、resolveされた値を表示することができました。

awaitとは?

MDNを読むと、

await 演算子は、async function によって Promise が返されるのを待機するために使用します。

とありました。

promiseの結果が返ってくるまで、async function関数の処理を一時中断するのですね。

.then()によるメソッドチェーンを使用しない書き方

また、.then()を用いるメソッドチェーンで繋げなくても、次の処理を書くことができます。

以下は、過去の課題7のコードです。

function addList(values) {
 const fragment = document.createDocumentFragment();

 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);
};

function fetchListData() {
 addLoading();
 return promise = new Promise(resolve => {
  setTimeout(() => resolve(attributes), 3000);
 });
}

fetchListData().then(values => {
 removeLoading();
 addList(values)
});
 

promiseを使用した関数fetchListData()を実行した後に、.then() で次の処理につなげていました。

今回のasync/awaitの利用では、addList()関数内でawaitを使用。

const values = await fetchListData();

fetchListData()関数をawaitすることで、

  1. fetchListData() の値が返ってくるまで待機
  2. 値が返ってきたら removeLoading()を実行してローディング画像を取り除く
  3. fetchListData()の値を使用して、表示したいリストを作成

というように、簡潔でわかりやすい順番でコードを書くことができました!!

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();

Promiseのインスタンス作成の書き方

塾生のさえさん(@sae_prog)からレビューをいただきました。ありがとうございます!

以前の課題から、promiseの部分をこのように書いていました。

function fetchListData() {
 addLoading();
 const promise = return new Promise((resolve) => {
  setTimeout(() => resolve(attributes), 3000);
 });
}
const promiseで新しいpromiseインスタンスを宣言していますが、こちらのconstは必要ないと気づくことができました。
この後のコードで、constで宣言した変数promiseが呼び出されることはないし、new Promise でインスタンスを宣言するときも変数を必ず使用する必要はないからです(必ず必要だとずっと勘違いしていた。。)
function fetchListData() {
 addLoading();
  return new Promise((resolve) => {
  setTimeout(() => resolve(attributes), 3000);
 });
}
レビューのおかげでよりすっきりしたコードになり嬉しいです。
//

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

あとがき

お忙しい時間を割いて課題を確認してくださった塾生のさえさん(@sae_prog)・もなかさん(@ruby443n)ありがとうございました!!

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

 

今日は以上です。

//

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

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

タイトルとURLをコピーしました