このチャプターについて
前のチャプターを通して、Promise chain の基本的な動きが分かったと思います。ここからは Promise chain において値をつないでいく処理を考えてみたいと思います。
次のチェーンに値を繋ぐ
then()
メソッドの引数のコールバックには入力として前の then()
メソッドのコールバック内にて return
した値を渡すことができます。
先程のコードを更に改造して、実際にテストしてみます。再び実行の順番を予想してみてください。
// returnPromiseByFuncArg2AddChainValue.js
console.log("🦖 [A] MAINLINE(Start): Sync");
const returnPromise = (resolvedValue, order) => {
return new Promise((resolve) => {
console.log(`👻 ${order} Sync`);
resolve(resolvedValue);
});
};
returnPromise("🐵 1st Promise", "[B]")
.then((value1) => {
console.log("👦 [C]", value1);
return "value from 1st then";
})
.then((value2) => {
console.log("👦 [D]", value2);
// return "value from 2nd then";
})
.then((value3) => {
console.log("👦 [E]", value3);
});
returnPromise("🐵 2nd Promise", "[F]")
.then((value1) => {
console.log("👦 [G]", value1);
return "value from 1st then";
})
.then((value2) => {
console.log("👦 [H]", value2);
return "value from 2nd then";
})
.then((value3) => {
console.log("👦 [I]", value3);
});
console.log("🦖 [J] MAINLINE(End): Sync");
答え
答えは以下のようになります。
❯ deno run returnPromiseByFuncArg2AddChainValue.js
🦖 [A] MAINLINE(Start): Sync
👻 [B] Sync
👻 [F] Sync
🦖 [J] MAINLINE(End): Sync
👦 [C] 🐵 1st Promise
👦 [G] 🐵 2nd Promise
👦 [D] value from 1st then
👦 [H] value from 1st then
👦 [E] undefined
👦 [I] value from 2nd then
アルファベットに数字をつけてみると分かりやすくなります。
// returnPromiseByFuncArg2AddChainValue-num.js
console.log("🦖 [1] MAINLINE(Start): Sync");
const returnPromise = (resolvedValue, order) => {
return new Promise((resolve) => {
console.log(`👻 ${order} Sync`);
resolve(resolvedValue);
});
};
returnPromise("🐵 1st Promise", "[2]")
.then((value1) => {
console.log("👦 [5]", value1);
return "value from 1st then";
})
.then((value2) => {
console.log("👦 [7]", value2);
// return "value from 2nd then";
})
.then((value3) => {
console.log("👦 [9]", value3);
});
returnPromise("🐵 2nd Promise", "[3]")
.then((value1) => {
console.log("👦 [6]", value1);
return "value from 1st then";
})
.then((value2) => {
console.log("👦 [8]", value2);
return "value from 2nd then";
})
.then((value3) => {
console.log("👦 [10]", value3);
});
console.log("🦖 [4] MAINLINE(End): Sync");
動きは前のコードと同じなので解説はしません。JS Visualizer 9000 で可視化したものは以下です。
- returnPromiseByFuncArg2AddChainValue.js
- ⚠️ 注意: JS Visualizer ではグローバルコンテキストは可視化されないので最初のマイクロタスク実行のタイミングについて誤解しないように注意してください
ポイントとしては、return
文をコメントアウトしてある then()
コールバックの次の then()
コールバックでは、渡されるはずの値がないので undefined
となっている点です。何も return
しない場合には次の then()
メソッドのコールバックの入力値は undefined
となるので注意してください。
チェーンの最後まで値を繋ぐ
Promise chain で「値を繋ぐ」ことが理解しづらい場合には次のコードを考えてみます。このコードでは、returnPromise()
関数の第一引数として渡した文字列 "1st Promise"
を Promise chain において then()
メソッドのコールバックで毎回 return
することで最後まで値を繋げています。
// chainValue.js
console.log("🦖 [1] MAINLINE(Start): Sync");
const returnPromise = (resolvedValue, order) => {
return new Promise((resolve) => {
console.log(`👻 ${order} Sync`);
resolve(resolvedValue);
});
};
// 文字列 "🐵 1st Promise" で解決された後にその値を最後まで連鎖させる
returnPromise("🐵 1st Promise", "[2]")
.then((value1) => {
console.log("👦 [4]", value1); // 🐵 1st Promise
return value1;
})
.then((value2) => {
console.log("👦 [5]", value2); // 🐵 1st Promise
return value2;
})
.then((value3) => {
console.log("👦 [6]", value3); // 🐵 1st Promise
return value3;
})
.then((value4) => {
console.log("👦 [7]", value4); // 🐵 1st Promise
});
console.log("🦖 [3] MAINLINE(End): Sync");
これを実行すると以下の出力を得ます。
❯ deno run chainValue.js
🦖 [1] MAINLINE(Start): Sync
👻 [2] Sync
🦖 [3] MAINLINE(End): Sync
👦 [4] 🐵 1st Promise
👦 [5] 🐵 1st Promise
👦 [6] 🐵 1st Promise
👦 [7] 🐵 1st Promise
value1 → value2 → value3 → value4 というように値 "1st Promise"
が最後まで連鎖できていることに注目してください。
then()
メソッドのコールバック関数の引数に数値をつけたのは考えやすくするためで別に同じ value
でもよいです。
// chainValueName.js
console.log("🦖 [1] MAINLINE(Start): Sync");
const returnPromise = (resolvedValue, order) => {
return new Promise((resolve) => {
console.log(`👻 ${order} Sync`);
resolve(resolvedValue);
});
};
// 文字列 "🐵 1st Promise" で解決された後にその値を最後まで連鎖させる
returnPromise("🐵 1st Promise", "[2]")
.then((value) => {
console.log("👦 [4]", value); // 🐵 1st Promise
return value;
})
.then((value) => {
console.log("👦 [5]", value); // 🐵 1st Promise
return value;
})
.then((value) => {
console.log("👦 [6]", value); // 🐵 1st Promise
return value;
})
.then((value) => {
console.log("👦 [7]", value); // 🐵 1st Promise
});
console.log("🦖 [3] MAINLINE(End): Sync");