生のプロミスではなく、プロミスの「作成者」(=プロミスを返す関数)を使用する方が簡単です。まず、次を定義します。
const fetchJson = (url, opts) => () => fetch(url, opts).then(r => r.json())
そのような「創造者」を返します。ここで、直列および並列チェーン用の2つのユーティリティを示します。これらは、生のプロミスと「作成者」の両方を受け入れます。
const call = f => typeof f === 'function' ? f() : f;
const parallel = (...fns) => Promise.all(fns.map(call));
async function series(...fns) {
let res = [];
for (let f of fns)
res.push(await call(f));
return res;
}
次に、メインコードは次のように書くことができます:
let [[getTokenData, writeToDBData], frontEndData] = await parallel(
series(
fetchJson(url_for_getToken),
fetchJson(url_for_writeToDB),
),
fetchJson(url_for_frontEnd),
)
専用の「クリエーター」ラッパーが気に入らない場合は、次のように定義できます。 fetchJson
通常どおり
const fetchJson = (url, opts) => fetch(url, opts).then(r => r.json())
インライン継続を適切な場所で使用するseries
か、parallel
呼び出される:
let [[getTokenData, writeToDBData], frontEndData] = await parallel(
series(
() => fetchJson('getToken'),
() => fetchJson('writeToDB'),
),
() => fetchJson('frontEnd'), // continuation not necessary, but looks nicer
)
アイデアをさらに進めるために、約束ではなく「作成者」を作成series
してparallel
返すことができます。このようにして、シリアルおよびパラレルプロミスの任意のネストされた「回路」を構築し、順番に結果を取得できます。完全な動作例:
const call = f => typeof f === 'function' ? f() : f;
const parallel = (...fns) => () => Promise.all(fns.map(call));
const series = (...fns) => async () => {
let res = [];
for (let f of fns)
res.push(await call(f));
return res;
};
//
const request = (x, time) => () => new Promise(resolve => {
console.log('start', x);
setTimeout(() => {
console.log('end', x)
resolve(x)
}, time)
});
async function main() {
let chain = series(
parallel(
series(
request('A1', 500),
request('A2', 200),
),
series(
request('B1', 900),
request('B2', 400),
request('B3', 400),
),
),
parallel(
request('C1', 800),
series(
request('C2', 100),
request('C3', 100),
)
),
);
let results = await chain();
console.log(JSON.stringify(results))
}
main()
.as-console-wrapper { max-height: 100% !important; top: 0; }