Webは不特定多数からのリクエストを取り扱う為にわざわざ順不同にしているので
それに逆らうならそれなりの意味があるはずです。
そしてその「逆らう要望」の内容により取るべき手段が変化します。
例えばMySQLのコネクション枯渇問題で排他制御を入れたいのなら
コネクションプールを利用するべきです。
promissやasync/awaitでは、そのような制御はできませんでした。
可能です。
原理としてはpromiseを定義する時
`const promise = new Promise(resolve => {実行内容});
こんな風にresolve関数を定義しますが、これを外部に持ち出す事で
関数の外部でresolveを叩いてpromiseを完了させる事が可能となります。
bash
1$ node
2Welcome to Node.js v14.17.4.
3Type ".help" for more information.
4
5> state = {}
6{}
7
8> promise = new Promise(resolve => {state.resolve = resolve})
9Promise { <pending> }
10
11> promise
12Promise { <pending> }
13
14> state.resolve()
15undefined
16
17> promise
18Promise { undefined } # <- 終了していることが確認出来る
要は各リクエストを数珠つなぎにしていくだけです。
js
1Promise.resolve(null)
2 .then(() => {
3 // resolveを外に取り出す
4 // 1個目のリクエストを良い感じに完了させる
5 })
6 .then(() => {
7 // resolveを外に取り出す
8 // 2個目のリクエストを良い感じに完了させる
9 })
10 .then(() => {
11 // resolveを外に取り出す
12 // 3個目のリクエストを良い感じに完了させる
13 })
Promiseは後から追加することも可能です。
js
1let promise = Promise.resolve(null);
2
3for (let i = 0; i < 3; i++) {
4 promise = promise.then(() => {
5 // resolveを外に取り出す
6 // i個目のリクエストを良い感じに完了させる。
7 })
8}
後はresolveの持ち出しと
Promiseの数珠つなぎを駆使して何とか書ききれば出来ます。
この辺は配給の列を準備するラッパーみたいな関数を用意して
これが全部完了したら貴方は動いても良いぞみたいな所までこぎつければ完了ですね。
js
1const express = require("express");
2
3const lineUp = () => {
4 // 上記のresolve持ち出しを駆使して取り出す
5 return resolve;
6}
7
8const app = express();
9app.get("/", async (req, res) => {
10 // これで後続のリクエストを待たせる
11 const resolve = await lineUp();
12
13 // DB等のアクセスで欲しいデータを用意する
14 const data = {name: "taro"};
15
16 // resolveを実行してブロッキングを開放
17 resolve(); // どんなエラーが発生してもこのresolve関数は実行しておきたい
18 res.json(data);
19});
ここのコアな部分を作るのはかなり面倒というか、
実装の手間と工数が必要ですし、リクエストが集中した時のメモリリーク対策等
まともに書いてたらキリないですし、責任も取れないのでぼかした感じで終了します。