scythercas
@scythercas

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Promiseの勉強中。関数の実行順序に関する質問です

Promiseの勉強をしていて、次のようなコードを書きました。

const promise1 = new Promise((resolve, reject) => {
    reject("rejectなんだ");
})
    .then(() => {
        console.log("resolveだ");
    })
    .catch((val) => {
        console.log(val);
    });

const promise2 = new Promise((resolve, reject) => {
    resolve("resolveなんだ");
})
    .then((val) => {
        console.log(val);
    })
    .catch(() => {
        console.log("rejectだ");
    });

Promise.all([promise1,promise2]).then(() => {
    console.log("全Promise終了");
})
Promise.race([promise1, promise2]).then(() => {
    console.log("あるPromise終了");
})

予想では、

resolveなんだ
rejectなんだ
全Promise終了
あるPromise終了

という表示でしたが、

実行結果は下のようになりました。
image.png

予想が違っていた原因は、関数が上から順に読み込まれ、同時に実行されると考えていたが、実際は全ての関数が読み込まれた状態で実行されたからだと考えておりますが、正しいでしょうか。

仮に正しい場合は、辞書的な言葉でこの順序で実行される理由を説明していただけると助かります。

どなたかご回答宜しくお願い致します。

0

1Answer

一部正しくない内容があったので修正して再回答します。

Promise の引数pthenメソッドの引数tcatchメソッドの引数cはどれも関数オブジェクトで、関数は未実行です。
new Promise(p)Promiseを作りpending状態にして関数pを呼び出します。
関数pに渡されたresolve(値)を呼び出すとPromiseに値が設定されfulfilled状態になり、関数tを呼ぶ準備ができた状態になります。
関数pに渡されたreject(値)を呼び出すとPromiseに値が設定されreject状態になり、関数cを呼ぶ準備ができた状態になります。
Promise.allPromise.racePromiceを作るだけで何も呼び出しません。
スクリプトをすべて実行し終わってJavaScript実行エンジンに制御が戻ると、Promiceの状態に応じて関数tや関数cを呼び出します。
allは、リストのすべてのPromiseが完了状態になるとallの関数tが呼び出されます。
raceは、リストのいずれかのPromiseが完了した時点でraceの関数tが呼び出されるので、allよりも先にraceの結果が表示されることになります。

試しに、ソースコードの最後で require('process').exit(); を実行するようにしてJavaScript実行エンジンNode.jsで実行してみると、JavaScript実行エンジンに制御が戻らずにプログラムが終了するため、Promisethencatchが呼び出されないことが確認できます。

console.log("start")

function callResolve(resolve, reject) {
    console.log('called callResolve');
    resolve("resolveなんだ");
}
function callReject(resolve, reject) {
    console.log('called callReject');
    reject("rejectなんだ");
}
function calledThen(resolve, reject) {
    console.log('called calledThen');
}
function calledCatch(resolve, reject) {
    console.log('called calledCatch');
}
function printValue(val) {
    console.log(val);
}
function doneAll() {
    console.log("全Promise終了");
}
function doneRace() {
    console.log("あるPromise終了");
}

const promise1 = new Promise(callReject).then(calledThen).catch(printValue);
console.log('promise1');
const promise2 = new Promise(callResolve).then(printValue).catch(calledCatch);
console.log('promise2');
Promise.all([promise1, promise2]).then(doneAll);
console.log('promise3');
Promise.race([promise1, promise2]).then(doneRace);
console.log('promise4');

// require('process').exit();
console.log("end")
実行結果
start
called callReject
promise1
called callResolve
promise2
promise3
promise4
end
resolveなんだ
rejectなんだ
あるPromise終了
全Promise終了
exitした場合
start
called callReject
promise1
called callResolve
promise2
promise3
promise4
1Like

Comments

  1. @scythercas

    Questioner

    ご回答ありがとうございました!!
    おかげさまで理解できました。

    Promise文の仕様から関数オブジェクトの仕様、検証の仕方まで大変参考になりました。

Your answer might help someone💌