Skip to content

Instantly share code, notes, and snippets.

@PetukhovArt
Created December 29, 2024 19:28
Show Gist options
  • Save PetukhovArt/220dab72f4abb356194daa77b83bb3b6 to your computer and use it in GitHub Desktop.
Save PetukhovArt/220dab72f4abb356194daa77b83bb3b6 to your computer and use it in GitHub Desktop.
const fetchMock = (endpoint) => {
console.log("fetched --> " + endpoint);
// 'fetched' '/3000'
// 'fetched' '/error'
// 'fetched' '/2000'
// 'fetched' '/500'
// 'fetched' '/600'
const ms = Number(endpoint.slice(1));
return new Promise((resolve, reject) => {
if (endpoint === "/error" || Number.isNaN(ms)) {
reject(endpoint);
} else {
setTimeout(() => {
resolve(endpoint);
}, ms);
}
});
};
// В любой момент времени количество запросов не должно превышать установленный лимит.
// Как только один из них разрешился сразу отправляем следующий.
// очередность ответов должна совпадать с очередностью переданных ссылок;
// - один и тот же эндпоинт не должен опрашиваться более одного раза (мемоизация).
const requestQueue = (endpoints, callback, limit = 3) => {
const cache = new Map();
const promiseResults = [];
const executing = new Set();
return new Promise(async (resolve, _) => {
const tryResolveQueue = () => {
if (promiseResults.length === endpoints.length) {
resolve(promiseResults);
}
};
for (const endpoint of endpoints) {
if (cache.has(endpoint)) {
// если уже запрашивали ранее и есть res , возвращаем данные
const data = cache.get(endpoint);
if (data) {
callback(data);
promiseResults.push(data);
}
tryResolveQueue();
continue;
}
cache.set(endpoint, null);
const promise = fetchMock(endpoint);
const onResponse = (res) => {
cache.set(endpoint, res);
executing.delete(execute);
tryResolveQueue();
return res;
};
const execute = promise.then(onResponse, onResponse);
executing.add(execute);
promiseResults.push(execute);
const race = async () => {
return await new Promise((resolve, reject) => {
executing.forEach((pr) => {
pr.then(resolve).catch(reject);
});
});
};
if (executing.size >= limit) {
await race();
}
}
});
};
requestQueue(
["/3000", "/3000", "/3000", "/error", "/2000", "/500", "/600", "/error"],
(data) => console.log(data),
);
// ['/3000', '/3000', '/3000', '/error', '/2000', '/500', '/600', '/error']
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment