Skip to content

Instantly share code, notes, and snippets.

@senaev
Last active November 8, 2023 15:33
Show Gist options
  • Save senaev/7170513eaacea438da5487055966a761 to your computer and use it in GitHub Desktop.
Save senaev/7170513eaacea438da5487055966a761 to your computer and use it in GitHub Desktop.
const links = ['link1', 'link2', 'link1', 'link3', 'link1', 'link2', 'link2', 'link7'];
const expected = [1, 2, 1, 3, 1, 2, 2, 7];
const db = { link1: '1', link2: '2', link3: '3', link7: '7' };
function fetch(url) {
console.log(`fetching: ${url}`)
const response = db[url];
if (response === undefined) {
throw new Error('No such url');
}
return new Promise(resolve => {
const timeout = Math.random() * 1000 + 1000 + 20;
setTimeout(() => resolve(response), timeout);
});
}
function callOnce(fn) {
this.called = false;
return (...args) => {
if (this.called) {
throw new Error('Callback called second time');
}
this.called = true;
return fn(...args);
};
}
function test(results) {
if (!Array.isArray(results) || results.toString() !== expected.toString()) {
console.error(`Expected: ${expected.toString()}`);
console.error(`Received: ${results.toString()}`);
return
}
console.log('Test passed');
}
console.clear();
parallelLimit(links, 3, callOnce(test));
function parallelLimit(urls, streams, cb) {
if (urls.length === 0) {
cb([]);
}
const copyLinks = [...urls];
let currentStreams = 0;
let callCount = 0;
const res = [];
function request(count) {
if (copyLinks.length === 0) {
return;
}
if (currentStreams < streams) {
const currentLink = copyLinks.splice(0, 1);
currentStreams++;
callCount++;
fetch(currentLink).then(result => {
currentStreams--;
res[count] = result;
}).catch(err => {
res[count] = err;
}).finally(() => {
request(callCount);
if (urls.length === res.length) {
cb(res);
}
})
}
}
for (let i = 0; i < streams; i++) {
request(callCount);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment