6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

2022年2月15日 非同期処理:コールバック/Promise/Async - Promise.resolve (JavaScript Primer)

Promise.resolve

Promise.resolveメソッドはFulfilledの状態となったPromiseインスタンスを作成します。

const fulfilledPromise = Promise.resolve();

Promise.resolveメソッドは以下のコードの糖衣構文(シンタックスシュガー)です。

// const fulfilledPromise = Promise.resolve(); と同じ意味
const fulfilledPromise = new Promise((resolve) => {
    resolve();
});

上記はresolveを実行するだけの関数です。

Promise.resolveメソッドは引数にresolveされる値を渡すこともできます。

// `resolve(42)`された`Promise`インスタンスを作成する
const fulfilledPromise = Promise.resolve(42);
fulfilledPromise.then(value => {
    console.log(value); // => 42
});

new演算子を使用した場合とPromise.resolveメソッドを使った場合をコード例として書きました。

const fulfilledPromise = Promise.resolve(42);
fulfilledPromise.then(value => {
    console.log(value); // => 42
});
const fulfilledPromise2 = new Promise((resolve) => {
    resolve("yano");
});
fulfilledPromise2.then(v => {
   console.log(v); // => yano
});

両者は同じですが、メソッドの挙動を理解するために書きました。

Promise.resolveメソッドで作成したFulfilledの状態となったPromiseインスタンスに対してもthenメソッドでコールバック関数を登録できます。 状態が変化済みのPromiseインスタンスにthenメソッドで登録したコールバック関数は、常に非同期なタイミングで実行されます。

常に非同期的なタイミングという点がピンと来なかったので検証しました。

基本的には同期処理が終わった後に非同期処理であるPromiseの処理が呼び出されるようです。 ▼以下の出力結果は1→2→3→4です。

const promise = Promise.resolve();
promise.then(() => {
    console.log("3. コールバック関数が実行されました");
});
console.log("1. 同期的な処理が実行されました");

promise.then(() => {
    console.log("4. コールバック関数が実行されました");
});
console.log("2. 同期的な処理が実行されました");

同期処理は、上から順に一つの処理が終わるのを待ってから次の処理が実行されていきます。

対して、非同期処理とは、上から順に処理が実行されるのは同じですが、一つの処理が終了するのを待たずに、次の処理を実行します。

メインスレッドではJavaScriptのコードの実行とレンダリングを行います。

JavaScriptではメインスレッドで一部の例外を除き非同期処理が並行処理として扱われます。 並行処理とは、処理を一定の単位ごとに分けて処理を切り替えながら実行することです。

今回でいうPromiseやsetTimeOutのような非同期処理はメインスレッドの並びから離れて次の処理に譲ります。

別の言い方にすると、PromiseやsetTimeOutなどの非同期処理は実行されずにタスクキューという領域で一時的に管理され、同期処理が終わった後に非同期処理がメインスレッドで実行されます。

Promise.reject

Promise.rejectメソッドもresolve()と同じ要領です。 Rejectedの状態となったPromiseインスタンスを作成します。

const rejectedPromise = Promise.reject(new Error("エラー"));

上記の構文は以下の糖衣構文です。

const rejectedPromise = new Promise((resolve, reject) => {
    reject(new Error("エラー"));
});

Promise.rejectメソッドで作成したRejected状態のPromiseインスタンスに対してもthenやcatchメソッドでコールバック関数を登録できます。Rejected状態へ変化済みのPromiseインスタンスに登録したコールバック関数は、常に非同期なタイミングで実行されます。これはFulfilledの場合と同様です。

Promise.reject(new Error("エラー")).catch(() => {
    console.log("2. コールバック関数が実行されました");
});
console.log("1. 同期的な処理が実行されました");

参考

Promise.resolve