es6-promiseをコードリーディングしてPromiseの挙動を理解する
最初に
es6-promiseはPromiseの基本的な仕組みを自前で実装して、以前のJavaScriptでも動くようになっています。
es6-promiseのコードから主要な部分をコードリーディングしてPromiseの仕組みを理解していきます。
コードの理解
状態管理
Promiseは下記のように3つの状態を管理しています。
早期returnをして、Promiseの状態がpendingの時だけ状態を変化するようにしています。
- PENDING: undefined(初期状態)
- FUFILLED: 1(resolveが呼ばれ成功となった状態)
- REJECTED: 2(rejectが呼ばれ失敗となった状態)
下記で状態の初期設定をしています。
ユーザー任意のコードを実行後にresolveが呼ばれた場合は下記が実行されます。
pendingではない場合は、早期returnするようにしており、pendingの場合は状態をFULFILLEDに変更しています。
ユーザーが任意の実装をして、rejectが呼ばれた場合は下記が実行されます。
pendingではない場合は、早期returnするようにしており、pendingの場合は状態をREJECTEDに変更しています。
キューの仕組み
キューは非同期的にコールバック(thenやcatchメソッド)を実行するための実装です。
setTimeoutを利用してタスクキューに追加して、非同期的にflushを実行しています。
flushでは、キューに登録されたコールバックを順番に取り出して実行します。
setTimeout以外にも環境によって非同期実行をする方法を分けています。
fulfillかrejectが呼ばれた後にhandlersにコールバックが登録されていれば、asapが実行されます。
asapメソッドはコールバックとその引数をキューに登録して、初回の登録時にscheduleFlushを呼び出します(非同期処理をタスクキューに登録)。上述のscheduleFlushのコードのように非同期でコールバックを処理する準備をしています。
thenメソッド
then が呼ばれると、状態がpendingの場合は成功時と失敗時のコールバックがhandlersキュー(非同期処理が登録されるコールバックのリスト)に登録されます。
また、状態がresolvedまたは rejectedの場合は登録されたコールバックがinvokeCallbackによって非同期に実行されます。
FIFOで複数の.thenチェーンが登録されている場合、それらを登録順に実行するようにしています。
Promiseをreturnすることでコールバックチェーンが続けられるようにして、何度もthenを呼び出せるようにしています。
まとめ
es6-promiseの実装を参考にPromiseの挙動を確認していきました。
OSSを見て理解を深めていくことは、土台となる技術の仕組みの理解を進めることができ、良いと感じました。
Discussion