// implementation of the "eternal heat" and "raceways" approach.
function initializeRaceway(raceways, promise, controller, handler) {
promise
.then(response => {
raceways
// mutate an `EternalHeat` instance's locally scoped `raceways`
// array by slicing the outpaced `raceway` items from it ...
.splice(0, raceways.indexOf(controller))
// ... and for each outpaced `raceway` item prevent the execution
// of the `EternalHeat`-instance sprint-end handler by aborting
// the item- and promised-related `AbortController` instance.
.forEach(controller =>
controller.abort()
);
handler(response);
}).catch(reason => {});
raceways
.push(controller);
}
class EternalHeat {
constructor(sprintEndHandler) {
const raceways = [];
this.addRaceway = (promise, abortController) =>
initializeRaceway(
raceways,
promise,
abortController,
sprintEndHandler,
);
}
}
// test case specific code
console.log(`... running ...
should sequentially log the 'userId'
related response data of ... 3, 6, 7.`);
const delayedApiRequestData = [
['https://jsonplaceholder.typicode.com/users/1/posts', 4600],
['https://jsonplaceholder.typicode.com/users/2/posts', 4300],
['https://jsonplaceholder.typicode.com/users/3/posts', 4000], // 1st
['https://jsonplaceholder.typicode.com/users/4/posts', 5600],
['https://jsonplaceholder.typicode.com/users/5/posts', 5300],
['https://jsonplaceholder.typicode.com/users/6/posts', 5000], // 2nd
]
function createDelayedAbortableApiRequest(url, delay) {
const controller = new AbortController();
const { signal } = controller;
return [
(async function delayedAbortableApiRequest() {
await new Promise(resolve => setTimeout(resolve, delay));
return await fetch(url, { signal });
})(),
controller,
];
}
async function handleResponseData(response) {
const data = await response.json();
console.log({ data });
}
const heat = new EternalHeat(handleResponseData);
setTimeout(() => heat
.addRaceway(
...createDelayedAbortableApiRequest(
'https://jsonplaceholder.typicode.com/users/7/posts', 0, // 3rd
)
),
6000
);
delayedApiRequestData
.map(([url, delay]) =>
createDelayedAbortableApiRequest(url, delay)
)
.forEach(([promise, abortController]) =>
heat.addRaceway(promise, abortController)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }