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 ウゼェ」 という方は、飲み屋にでも誘っていただければ快くパブリックドメインにいたしますので、お気軽にどうぞ!!
