Sẽ dễ dàng hơn nếu bạn làm việc với lời hứa "người tạo" (= chức năng trả lại lời hứa) thay vì lời hứa thô. Đầu tiên, xác định:
const fetchJson = (url, opts) => () => fetch(url, opts).then(r => r.json())
trong đó trả về một "tác giả" như vậy. Bây giờ, đây là hai tiện ích cho chuỗi nối tiếp và song song, chấp nhận cả lời hứa thô và "người tạo":
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;
}
Sau đó, mã chính có thể được viết như thế này:
let [[getTokenData, writeToDBData], frontEndData] = await parallel(
series(
fetchJson(url_for_getToken),
fetchJson(url_for_writeToDB),
),
fetchJson(url_for_frontEnd),
)
Nếu bạn không thích trình bao bọc "người tạo" chuyên dụng, bạn có thể xác định fetchJson
bình thường
const fetchJson = (url, opts) => fetch(url, opts).then(r => r.json())
và sử dụng các phần tiếp theo nội tuyến ngay tại nơi series
hoặc parallel
được gọi là:
let [[getTokenData, writeToDBData], frontEndData] = await parallel(
series(
() => fetchJson('getToken'),
() => fetchJson('writeToDB'),
),
() => fetchJson('frontEnd'), // continuation not necessary, but looks nicer
)
Để đưa ý tưởng đi xa hơn, chúng ta có thể thực hiện series
và parallel
trả lại "người sáng tạo" thay vì hứa hẹn. Bằng cách này, chúng ta có thể xây dựng các "mạch" lồng nhau tùy ý của các lời hứa nối tiếp và song song và nhận được kết quả theo thứ tự. Hoàn thành ví dụ làm việc:
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; }