-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathPromise.concurrent.js
More file actions
90 lines (72 loc) · 1.61 KB
/
Promise.concurrent.js
File metadata and controls
90 lines (72 loc) · 1.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// @source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols
//
const makeIterable = (array) => {
if (array.next) {
return array;
}
let nextIndex = 0;
return {
next: () =>
nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true}
};
};
const throttledAll = (source, concurrency = 5) =>
new Promise((res, rej) => {
const it = makeIterable(source);
let i = 0;
let collected = 0;
let lastRun = 0;
let iteratorDone = false;
let error = false;
let responses = [];
const runNext = () => {
/**
* Do not proceed if we've already caught an error.
*/
if (error || iteratorDone) {
return;
}
const next = it.next();
/**
* Do not proceed if we're done
*/
if (next.done) {
iteratorDone = true;
return;
}
runner(i++, next.value);
};
const didSucceed = (id, result) => {
collected++;
responses[id] = result;
if (iteratorDone && collected > lastRun) {
res(responses);
} else {
runNext();
}
};
const didError = e => {
error = true;
rej(e);
};
const runner = (id, fn) => {
lastRun = id;
try {
fn()
.then(resp => didSucceed(id, resp))
.catch(didError);
} catch (e) {
didError(e);
}
};
for (let ii = 0; ii < concurrency; ii++) {
runNext();
}
})
;
if (typeof Promise !== 'undefined') {
Promise.throttledAll = throttledAll;
}
module.exports = throttledAll;