Promiseをちゃんと理解したい①

2020/12/05

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

コールバックの問題点

Promiseが導入される前はコールバック関数を使って非同期処理の実行順序を保証したり,例外処理を行っていましたが,いくつか問題点があります。

複数の非同期処理の実行順序を保証しようとすると,ネストが深くなっていってしまい非常に可読性が悪くなります。いわゆるコールバック地獄です。
例外処理を行う場合も,共通のルールを使用することが一般的だったようですが,あくまで共通ルールというだけなので強制力がなく,人によって書き方がバラバラになってしまいます。

これらの問題を解決してくれるのがPromiseオブジェクトです。

Promiseオブジェクトって?

ES2015より導入された非同期処理の結果を表現するビルトインオブジェクトで,非同期処理を統一的なインターフェースで扱うことを目的にしています。
コールバックで例外処理を行うときは,共通ルールとして成功の場合は第一引数にnull,第二引数に結果を渡し,失敗した場合は第一引数にエラーオブジェクトを渡していました。
Promiseでは,非同期処理が成功したときのコールバック関数をthenメソッドへ,失敗したときのコールバック関数をcatchメソッドへ渡します。

コールバック関数のときと異なり,Promiseでは引数に渡せるものが決められているためやり方が統一されます。
複雑な非同期処理も統一されたインターフェースがあることでパターン化できるのがPromiseのメリットです。

実際にPromiseオブジェクトを使ってみる

// Promiseオブジェクトを返す 非同期処理
const asyncFunc = (value) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (value) {
        resolve({'value': value}); // 
      } else {
        reject(new Error('value is null'));
      }
    }, 500);
  });
};

// 成功した場合のコールバック関数
const onFulfilled = (result) => {
  console.log(result);
};

// 失敗した場合のコールバック関数
const onRejected = (error) => {
  console.log(error.message);
};

// thenメソッドに成功した場合,catchメソッドに失敗した場合のコールバック関数を渡す
asyncFunc('ばりゅー').then(onFulfilled).catch(onRejected); // 実行結果: { value: 'ばりゅー' }
asyncFunc().then(onFulfilled).catch(onRejected); // 実行結果: value is null

// thenメソッドの第一引数に成功した場合,第二引数に失敗した場合のコールバック関数を渡す
asyncFunc('ばりゅー').then(onFulfilled, onRejected); // 実行結果: { value: 'ばりゅー' }
asyncFunc().then(onFulfilled, onRejected); // 実行結果: value is null

thenメソッドは成功,失敗のコールバック関数を受け取ることができる。
成功時だけのコールバック関数,失敗時だけのコールバック関数を登録することもできるが,失敗時は第一引数にundefinedを渡す必要があり,わかりにくいため基本的にはcatchメソッドを使うようにしましょう。

成功時のコールバック関数 → thenメソッド
失敗時のコールバック関数 → catchメソッド
これだけ覚えておく。

例外

Promiseのコンストラクタ内で例外が発生した場合は自動的にキャッチしてくれます。
失敗したときと同様にcatchメソッドで登録したときのコールバック関数が呼び出されます。

// Promiseコンストラクタ内で例外を発生させる
const asyncFunc = () => {
  return new Promise((resolve, reject) => {
    throw new Error('例外が発生しました');
  });
};

// 失敗時と同様にcatchメソッドに登録したコールバック関数が実行される
asyncFunc().catch((error) => { console.log(error.message)});

Promiseの状態

Promiseインスタンスには状態が3つ存在します。

  • Fulfilled → 成功時
  • Rejected → 失敗時
  • Pending → 結果待ち

FulfilledかRejectedの状態になったら変化しない。

まとめ

改めてPromiseオブジェクトについて勉強してみたけど,全然理解せず使ってたなと。
いつも,エラー文と挙動から試行錯誤して実装してたけど,これからはちゃんと理解して実装できそうですw

それではまた明日。

参考


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