AsyncFunctionをちゃんと理解したい

2020/12/07

非同期処理をちゃんと理解するぞ!
ということで,昨日(Promiseをちゃんと理解したい②)のPromiseに引き続き今日は Async Function をやっていきます。

AsyncFunctionって?

非同期処理を行う関数を定義できます。
関数の前にasyncをつけることで常にPromiseインスタンスを返す関数となります。

// AsyncFunctionを定義
const asyncFunc = async() => {
  return '値';
}

// asyncFunc関数はPromiseインスタンスを返す
asyncFunc().then(value => console.log(value));
// 実行結果
// 値

戻り値のPromiseインスタンス

AsyncFunctionが返す 3パターンのPromiseインスタンス

1. 値をreturnした場合 → その返り値を持つFulfilledなPromiseを返す

const resolveFunc = async() => {
  return '返り値';
};

resolveFunc().then(value => console.log(value));
// 実行結果
// 返り値

2. Promiseをreturnした場合 → その返り値のPromiseをそのまま返す

const asyncFunc = async() => {
  return new Promise((resolve, reject) => {
    Math.random() < 0.5 ? resolve() : reject();
  });
};

asyncFunc()
  .then(() => {
    console.log('Fulfilled');
  })
  .catch(() => {
    console.log('Rejected');
  });
// 実行結果
// Fulfilled または Rejected

3. 例外が発生した場合は → そのエラーを持つRejectedなPromiseを返す

const rejectFunc = async() => {
  throw new Error('例外');
};

rejectFunc().catch( err => console.log(err.message));
// 実行結果
// 例外

await式

AsyncFunctionではawait式が利用できます。
await式は右辺のPromiseの状態を評価して値を返します。
PromiseがFulfilledの場合は,resolveされた値がawait式の返り値となり,Rejectedの場合は,エラーをthrowします。
await式を使うことでtry-catch構文を使ってエラーをキャッチしたり,コールバック関数を使わずに非同期処理の流れを表現したりできるようになります。

const awaitFunc = async() => {
  console.log('非同期な処理');
};

const asyncFunc = async() => {
  await awaitFunc();
  console.log('Promiseインスタンスの状態が変わったら処理される');
}

asyncFunc().then(() => console.log('Fulfilled')).catch(() => console.log('Rejected'));
// 実行結果
// 非同期な処理
// Promiseインスタンスの状態が変わったら処理される
// Fulfilled

非同期処理でtry-catch構文を使う

await式ではRejectedされたときにエラーをthrowするので,try-catch構文を使うことができます。

const asyncFunc = async() => {
  // try-catch構文
  try {
    // エラーを発生させる
    const value = await Promise.reject(new Error('エラー'));
  } catch (error) {
    console.log(error.message);
  }
};

asyncFunc();
// 実行結果
// エラー

逐次的に非同期処理を行う

await式を使えばメソッドチェーンにしなくても同期処理と同じような表現で逐次的な非同期処理を書くことができます。

const asyncFunc = (timeoutMs) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if(timeoutMs) {
        resolve(`${timeoutMs}ミリ秒`);
      } else {
        reject(new Error('timeoutMs is null'));
      }
    }, timeoutMs);
  });
};

const awaitFunc = async() => {
  const timeoutA = await asyncFunc(3000);
  console.log(timeoutA);
  const timeoutB = await asyncFunc(5000);
  console.log(timeoutB);
  const timeoutNull = await asyncFunc(null);
}

awaitFunc().catch(err => console.log(err.message));
// 実行結果
// 3000ミリ秒
// 5000ミリ秒
// timeoutMs is null

まとめ

見やすい!わかりやすい!AsyncFunctionをできれば使っていきたくなりますね。
そして,Promiseを理解してないと,AsyncFunctionも理解できないです。
非同期処理はコールバック関数を理解してないとPromiseを理解できないし,Promiseを理解してないとAsyncFunctionを理解できないので,どれかひとつ覚えておけばいいってもんじゃなくて,全てやってみてはじめて理解できるというか。そんな感じですね。
だいぶ雰囲気でやってた非同期処理がわかってきました。
これで詰まってたアプリ開発も進むはず!

それではまた明日。

参考


書いた人: こへ
音楽と漫画と読書とアニメとスノボが好き。多趣味でいろんなことに興味有ります。 誰しもが一度は使った事があるもののIoT開発をしてます。
Twitterフォローお願いします。