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