JavaScript でスマートに非同期なコードを書くための Promise パターンの仕様のうち、then
メソッドに関する仕様であるPromises/A+の邦訳です。
お約束の文言ですが、この翻訳は間違ってるかもしれません。ご指摘・ご質問は大歓迎です。
この提言はPromises/A 仕様の提言の振る舞いを明確にし、かつ事実上の標準をカバーしつつ曖昧・問題のある部分を除いたものである。
Promises/Aと同様に、この提案はPromiseの作成・解決訳注 1・棄却訳注 2の方法については言及しない。
Promises/AからPromises/A+へのすべての差分は、Promises/Aとの差分(英語)に記述してある。
promise は、ある時点でまだ利用できない値を表現する。 promise を利用する主な方法としてthen
メソッドがある。
2.1. 「 promise 」とは、then
メソッドを定義するオブジェクト、または関数である。
2.2. 「 値 」とは、JavaScriptの文法として正しい何らかの値である(undefined
や promise を含む)。
2.3. 「 理由 訳注 3」とは、 promise が棄却された場合の理由を示す値である。
2.4. 「 変化してはならない 」とは、内容が不変的に同一であること(例: ===
)。しかし、深い不変でなくともよい解説 1。
promise は未解決(pending)、解決済(fulfilled)、棄却済(rejected)という3つの状態のいずれかをとる。
3.1.1. promise が未解決のとき、
3.1.1.1. 解決済か棄却済に遷移するかもしれない。
3.1.2. promise が解決済のとき、
3.1.2.1. 他の状態へと遷移してはならない。
3.1.2.2. 何かの 値 をもち、この 値 は 変化してはならない 。
3.1.3. promise が棄却済のとき、
3.1.3.1. 他の状態へと遷移してはならない。
3.1.3.2. 何らかの 理由 をもち、この 理由 は 変化してはならない 。
promise は、解決された 値 、または 理由 へのアクセス手段としてthen
メソッドを提供しなければならない。
promise がもつthen
メソッドは、2つの引数をとりうる。
promise.then(onFulfilled, onRejected)
3.2.1. onFulfilled
とonRejected
のどちらも省略可能である。
3.2.1.1. もしonFulfilled
が関数でなければ、無視しなければならない。
3.2.1.2. もしonRejected
が関数でなければ、無視しなければならない。
3.2.2. もしonFulfilled
が関数であれば、
3.2.2.1. promise
の解決時にonFulfilled
はpromise
の解決された 値 を第一引数として呼び出されなければならない。
3.2.2.2. onFulfilled
は1回よりも多く呼び出されてはならない。
3.2.2.3. onRejected
が呼び出されたときには、onFulfilled
は呼び出されてはならない。
3.2.3. もしonRejected
が関数であれば、
3.2.3.1. promise
の棄却時にonRejected
は 理由 を第一引数として呼び出されなければならない。
3.2.3.2. onRejected
は1回よりも多く呼び出されてはならない。
3.2.3.3. onFulfilled
が呼び出されたときには、onRejected
は呼び出されてはならない。
3.2.4. then
は4.1のonFulfilled
かonRejected
の戻り値を返さなければならない。
3.2.5. then
は、同一の promise 内で複数回呼び出されるかもしれない。
3.2.5.1. もしpromise
が解決されたならば、各onFulfilled
コールバックはthen
メソッドによって登録された順に実行されなければならない。
3.2.5.2. もしpromise
が棄却されたならば、各onRejected
コールバックはthen
メソッドによって登録された順に実行されなければならない。
3.2.6. then
は promise を返さなければならない 4.2。
promise2 = promise1.then(onFulfilled, onRejected);
3.2.6.1. もしonFulfilled
またはonRejected
のどちらかが promise ではない 値 を返したとき、promise2
はその 値 を結果として解決されなければならない解説 2。
3.2.6.2. もしonFulfilled
またはonRejected
のどちらかが例外を発生させたとき、promise2
はその例外を 理由 として棄却されなければならない。
3.2.6.3. もしonFulfilled
またはonRejected
のどちらかが promise を返したとき(以降ではreturnedPromise
とする)、promise2
はreturnedPromise
の状態を引き受けなければならない4.3:
3.2.6.3.1. もしreturnedPromise
が未解決の場合、promise2
はreturnedPromise
が解決されるか棄却されるまで未解決の状態でなければならない。
3.2.6.3.2. もしreturnedPromise
が解決済の場合、promise2
はreturnedPromise
と同じ 値 で解決されなければならない。
3.2.6.3.3. もしreturnedPromise
が棄却された場合、promise2
はreturnedPromise
と同じ 理由 で棄却されなければならない。
3.2.6.4. もしonFulfilled
が関数でなく、かつpromise1
が解決済の場合、promise2
はpromise1
と同じ 値 で解決されなければならない。
3.2.6.5. もしonRejected
が関数でなく、かつpromise1
が棄却済の場合、promise2
はpromise1
と同じ 理由 で棄却されなければならない。
4.1. 実用的には、この実装はsetTimeout
やsetImmediate
、process.nextTick
などのメカニズムを利用して、onFulfilled
やonRejected
がthen
で登録されたときと同じイベントループで実行されないことを保証しなければならないだろう。
4.2. ある実装がpromise2 === promise1
を許容している場合、この実装はすべての要件を満たしているといえる。このような実装では、どのような条件でpromise2 === promise1
となるのかをドキュメントに書いておく必要があるだろう。
4.3. このメカニズムはpromise2
がreturnedPromise
がもつ不特定な状態を担うときのものである。合理的なアプローチのひとつとして、returnedPromise.then(fulfillPromise2, rejectPromise2)
を呼び出すことが挙げられる:
4.3.1. fulfillPromise2
は第一引数のpromise2
を解決する関数である。
4.3.2. rejectPromise2
は第一引数のpromise2
を棄却する関数である。
このreturnedPromise
はPromises/A+に適わないかもしれないが、then
メソッドを持ち、promise2
が常にreturnedPromise
の状態と同じ状態をとるという要件を満足しないような何らかのオブジェクトにすることによって可能になるかもしれない。したがって、この方法はもっとも信頼できる努力を象徴するだろう訳注 4。
【ここに書かれているライセンスは原文に関してのライセンスです。この翻訳についてのライセンスについては最下部を参照願います】
Promises/A+ organizationは、Promises/A+仕様に関して法律の下で可能な限り著作権および関連する隣接権を放棄する。この成果物は米国から配信されている。
原文では fulfill (実行する、遂行する、履行する)。「 promise の戻り値が確定し、後続の処理が実行されること」という意味です。この文書では 解決 と訳しました。
原文では reject (拒絶する、拒否する、棄却する)。「 promise の例外処理を実行する」という意味です。この文書では 棄却 と訳しました。
原文では reason (理由)。棄却された理由のことです。
意味不明でした。対応する原文は:
Thus, the procedure here represents a best-faith effort.
です。意味がわかる方はコメントでご教示願います。
ようするに、あるオブジェクト同士が===
で常にtrue
と評価されればよい、ということを言っています。 つまりオブジェクトのプロパティについては不変性を保たなくてもよい、ということです。
ようするに、onFulfilled
やonRejected
がどんな 値 を返そうが、then
メソッドの戻り値は 必ず promise になるということです。
具体例を出しましょう。
var promise2 = promise1.then(function() { return 'foo' });
promise2.then(function(val) { console.log(val) }); // -> 'foo'と表示される。
これは promise ではない 値 が返されたとき、その 値 を解決結果とするように promise でラップしなさいよ、ということを言っているのですね。なんてわかりづらいのかしら…。
英語版はパブリックドメインなんですが、@OrgaChem もそこそこ苦労したし解説もつけたので MITライセンス でお願いします。「なにMITにしてんの @OrgaChem ウゼェ」 という方は、飲み屋にでも誘っていただければ快くパブリックドメインにいたしますので、お気軽にどうぞ!!