Skip to content

Instantly share code, notes, and snippets.

@alpox
Last active June 26, 2022 11:02
Show Gist options
  • Save alpox/96860d58e4b2011987cc53352ccace9a to your computer and use it in GitHub Desktop.
Save alpox/96860d58e4b2011987cc53352ccace9a to your computer and use it in GitHub Desktop.
Windowed fetch with slots
const delay = (ms) => new Promise((res) => setTimeout(res, ms));
const createWindowedFetch = (windowSize = 1000, reqPerWindow = 30) => {
const slots = [0];
const start = new Date().getTime();
let lastSlot = start;
return async (url, requestInit) => {
let firstFreeSlotIndex = slots.findIndex(
(allocated) => allocated < reqPerWindow
);
if (firstFreeSlotIndex === -1) {
firstFreeSlotIndex = slots.length;
}
slots[firstFreeSlotIndex] = (slots[firstFreeSlotIndex] ?? 0) + 1;
const currentSlotStart =
start +
Math.floor((new Date().getTime() - start) / windowSize) * windowSize;
const matchedSlotStart = currentSlotStart + firstFreeSlotIndex * windowSize;
if (firstFreeSlotIndex) {
await delay(matchedSlotStart - new Date().getTime());
}
if (lastSlot !== matchedSlotStart) {
slots.shift();
lastSlot = matchedSlotStart;
}
const response = await fetch(url, requestInit);
if (!response.ok)
throw new Error(`Request failed: ${await response.text()}`);
return response.json();
};
};
const windowedFetch = createWindowedFetch();
async function test() {
for (let i = 0; i < 100; i++) {
const start = performance.now();
windowedFetch("http://127.0.0.1:3000/test.json").then(() =>
console.log(`Request ${i} took ${performance.now() - start} ms`)
);
}
}
test();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment