Promiseは次のサンプルコードように、失敗したらrejectを、成功したらresolveを呼び出すような書き方をする。
new Promise((resolve, reject) => {
// ...
if (err) {
reject(err)
} else {
resolve()
}
})
このサンプルコードは、正常系と異常系でif分岐されており、resolveとrejectが両方呼ばれる可能性はない。
もしも、resolveとrejectの両方を呼び出したらどうなるのだろうか?
new Promise((resolve, reject) => {
reject()
resolve()
})
普通はこんなことはしないだろうが、Promiseの仕様を知っておくのは良さそうだ。
実験1: resolve→rejectの順で呼んでみる
実験してみよう。まずは、resolve→rejectの順で呼び出してみよう。
new Promise((resolve, reject) => {
resolve()
reject()
}).then(value => console.log('success'))
.catch(reason => console.log('failure'))
//=> success
この実行結果は、「success」になり、resolveが尊重されたかたちになった。
実験2: reject→resolveの順で呼んでみる
今度は逆に、rejectのほうを先に呼び出してみることにする。
new Promise((resolve, reject) => {
reject()
resolve()
}).then(value => console.log('success'))
.catch(reason => console.log('failure'))
//=> failure
今度の結果は「failure」になった。rejectのほうが採用されたことが分かる。
結論: 先に呼ばれたほうが採用される
「Promiseのresolveとrejectの両方を呼び出したらどうなってしまうのか?」の疑問への答えとしては、「先に呼ばれたほうが採用される」ということになりそうだ。
余談: 先勝ちと言っても、処理が中断されるわけではない
ちなみに、resolveとrejectどちらかが採用されるとは言え、Promiseに渡したexecuterの処理が中断されるわけではない。例えば、下記のコードでは、①でresolveが採用されるが、そのあとの②③の行も実行される。
new Promise((resolve, reject) => {
resolve() // ①
console.log('after resolve') // ②
reject() // ③
}).then(value => console.log('success'))