It's easier if you work with promise "creators" (= function that return promises) rather than raw promises. First, define:
const fetchJson = (url, opts) => () => fetch(url, opts).then(r => r.json())
which returns such a "creator". Now, here are two utilities for serial and parallel chaining, which accept both raw promises and "creators":
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;
}
Then, the main code can be written like this:
let [[getTokenData, writeToDBData], frontEndData] = await parallel(
series(
fetchJson(url_for_getToken),
fetchJson(url_for_writeToDB),
),
fetchJson(url_for_frontEnd),
)
If you don't like the dedicated "creator" wrapper, you can define fetchJson
normally
const fetchJson = (url, opts) => fetch(url, opts).then(r => r.json())
and use inline continuations right where series
or parallel
are called:
let [[getTokenData, writeToDBData], frontEndData] = await parallel(
series(
() => fetchJson('getToken'),
() => fetchJson('writeToDB'),
),
() => fetchJson('frontEnd'), // continuation not necessary, but looks nicer
)
To bring the idea further, we can make series
and parallel
return "creators" as well rather than promises. This way, we can build arbitrary nested "circuits" of serial and parallel promises and get the results in order. Complete working example:
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; }