[ES2015] Promise
PromiseはES2015で導入された非同期処理の結果を表現するビルトインオブジェクトです。
エラーファーストコールバックは非同期処理を扱うコールバック関数の最初の引数にエラーオブジェクトを渡すというルールでした。
Promiseはこれを発展させたもので、単なるルールではなくオブジェクトという形にして非同期処理を統一的なインターフェースで扱うことを目的にしています。
Promiseはビルトインオブジェクトであるためさまざまなメソッドを持ちますが、 まずはエラーファーストコールバックとPromiseでの非同期処理のコード例を比較してみます
エラーファーストコールバック
- ECMAScript 2015(ES2015)でPromiseが仕様に入るまで、非同期処理中に発生した例外を扱う仕様はありませんでした。
このため、ES2015より前までは、エラーファーストコールバックという非同期処理中に発生した例外を扱う方法を決めたルールが広く使われていました。
エラーファーストコールバックとは、次のような非同期処理におけるコールバック関数の呼び出し方を決めたルールです。
- 処理が失敗した場合は、コールバック関数の1番目の引数にエラーオブジェクトを渡して呼び出す
- 処理が成功した場合は、コールバック関数の1番目の引数にはnullを渡し、2番目以降の引数に成功時の結果を渡して呼び出す
つまり、ひとつのコールバック関数で失敗した場合と成功した場合の両方を扱うルールとなります。
Promiseインスタンスの作成
- Promiseはnew演算子でPromiseのインスタンスを作成して利用します。
- このときのコンストラクタにはresolveとrejectの2つの引数を取るexecutorと呼ばれる関数を渡します。
- executor関数の中で非同期処理を行い、
- 非同期処理が成功した場合はresolve関数を呼び、
- 失敗した場合はreject関数を呼び出します。
const executor = (resolve, reject) => { // 非同期の処理が成功したときはresolveを呼ぶ // 非同期の処理が失敗したときはrejectを呼ぶ }; const promise = new Promise(executor);
Promiseチェーン
- Promiseは非同期処理における統一的なインターフェースを提供するビルトインオブジェクトです。
- Promiseによる統一的な処理方法は複数の非同期処理を扱う場合に特に効力を発揮します。
- これまでは、1つのPromiseインスタンスに対してthenやcatchメソッドで1組のコールバック処理を登録するだけでした。
- 非同期処理が終わったら次の非同期処理というように、複数の非同期処理を順番に扱いたい場合もあります。
- Promiseではこのような複数の非同期処理からなる一連の非同期処理を簡単に書く方法が用意されています。
- この仕組みのキーとなるのがthenやcatchメソッドは常に新しいPromiseインスタンスを作成して返すという仕様です。
- そのためthenメソッドの返り値であるPromiseインスタンスにさらにthenメソッドで処理を登録できます。
- これはメソッドチェーンと呼ばれる仕組みですが、この書籍ではPromiseをメソッドチェーンでつなぐことをPromiseチェーンと呼びます(詳細は「配列」の章を参照)。
[ES2017] Async Function
- ES2017では、Async Functionという非同期処理を行う関数を定義する構文が導入されました。
Async Functionは通常の関数とは異なり、必ずPromiseインスタンスを返す関数を定義する構文です。
Async Functionは次のように関数の前にasyncをつけることで定義できます。
- このdoAsync関数は常にPromiseインスタンスを返します。
async function doAsync() { return "値"; } // doAsync関数はPromiseを返す doAsync().then(value => { console.log(value); // => "値" });
- 重要なこととしてAsync FunctionはPromiseの上に作られた構文です。
- そのためAsync Functionを理解するには、Promiseを理解する必要があることに注意してください。
- またAsync Function内ではawait式というPromiseの非同期処理が完了するまで待つ構文が利用できます。
- await式を使うことで非同期処理を同期処理のように扱えるため、Promiseチェーンで実現していた処理の流れを読みやすく書けます。