1 | | // Generated by CoffeeScript 1.4.0 |
2 | | /* |
3 | | each(elements) |
4 | | .mode(parallel=false|true|integer) |
5 | | .on('item', callback) |
6 | | .on('error', callback) |
7 | | .on('end', callback) |
8 | | .on('both', callback) |
9 | | Chained and parallel async iterator in one elegant function |
10 | | */ |
11 | | |
12 | 1 | module.exports = function(elements) { |
13 | 52 | var eacher, errors, events, isObject, keys, next, parallel, run, times, type; |
14 | 52 | type = typeof elements; |
15 | 52 | if (elements === null || type === 'undefined' || type === 'number' || type === 'string' || type === 'function' || type === 'boolean') { |
16 | 16 | elements = [elements]; |
17 | 36 | } else if (!Array.isArray(elements)) { |
18 | 9 | isObject = true; |
19 | | } |
20 | 52 | if (isObject) { |
21 | 9 | keys = Object.keys(elements); |
22 | | } |
23 | 52 | errors = []; |
24 | 52 | parallel = 1; |
25 | 52 | events = { |
26 | | item: [], |
27 | | error: [], |
28 | | end: [], |
29 | | both: [] |
30 | | }; |
31 | 52 | times = []; |
32 | 52 | eacher = {}; |
33 | 52 | eacher.total = keys ? keys.length : elements.length; |
34 | 52 | eacher.started = 0; |
35 | 52 | eacher.done = 0; |
36 | 52 | times = 1; |
37 | 52 | eacher.paused = 0; |
38 | 52 | eacher.readable = true; |
39 | 52 | eacher.pause = function() { |
40 | 10 | return eacher.paused++; |
41 | | }; |
42 | 52 | eacher.resume = function() { |
43 | 10 | eacher.paused--; |
44 | 10 | return run(); |
45 | | }; |
46 | 52 | eacher.parallel = function(mode) { |
47 | 34 | if (typeof mode === 'number') { |
48 | 15 | parallel = mode; |
49 | 19 | } else if (mode) { |
50 | 16 | parallel = mode; |
51 | | } else { |
52 | 3 | parallel = 1; |
53 | | } |
54 | 34 | return eacher; |
55 | | }; |
56 | 52 | eacher.times = function(t) { |
57 | 6 | times = t; |
58 | 6 | return eacher; |
59 | | }; |
60 | 52 | eacher.on = function(ev, callback) { |
61 | 136 | events[ev].push(callback); |
62 | 136 | return eacher; |
63 | | }; |
64 | 52 | run = function() { |
65 | 16723 | var args, emit, emitError, index, lboth, lerror, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3; |
66 | 16723 | if (eacher.paused) { |
67 | 35 | return; |
68 | | } |
69 | 16688 | if (eacher.done === eacher.total * times || (errors.length && eacher.started === eacher.done)) { |
70 | 52 | eacher.readable = false; |
71 | 52 | if (errors.length) { |
72 | 10 | if (parallel !== 1) { |
73 | 6 | if (errors.length === 1) { |
74 | 3 | args = [errors[0], errors]; |
75 | | } else { |
76 | 3 | args = [new Error("Multiple errors (" + errors.length + ")"), errors]; |
77 | | } |
78 | | } else { |
79 | 4 | args = [errors[0]]; |
80 | | } |
81 | 10 | lerror = events.error.length; |
82 | 10 | lboth = events.both.length; |
83 | 10 | emitError = lerror || (!lerror && !lboth); |
84 | 10 | _ref = events.error; |
85 | 10 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { |
86 | 8 | emit = _ref[_i]; |
87 | 8 | if (emitError) { |
88 | 8 | emit.apply(null, args); |
89 | | } |
90 | | } |
91 | | } else { |
92 | 42 | args = []; |
93 | 42 | _ref1 = events.end; |
94 | 42 | for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { |
95 | 36 | emit = _ref1[_j]; |
96 | 36 | emit(); |
97 | | } |
98 | | } |
99 | 52 | _ref2 = events.both; |
100 | 52 | for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { |
101 | 13 | emit = _ref2[_k]; |
102 | 13 | emit.apply(null, args); |
103 | | } |
104 | 52 | return; |
105 | | } |
106 | 16636 | if (errors.length !== 0) { |
107 | 10 | return; |
108 | | } |
109 | 16626 | while ((parallel === true ? (eacher.total * times - eacher.started) > 0 : Math.min(parallel - eacher.started + eacher.done, eacher.total * times - eacher.started))) { |
110 | 16670 | if (errors.length !== 0) { |
111 | 9 | break; |
112 | | } |
113 | 16661 | index = Math.floor(eacher.started / times); |
114 | 16661 | eacher.started++; |
115 | 16661 | try { |
116 | 16661 | _ref3 = events.item; |
117 | 16661 | for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { |
118 | 16661 | emit = _ref3[_l]; |
119 | 16661 | switch (emit.length) { |
120 | | case 1: |
121 | 6 | args = [next]; |
122 | 6 | break; |
123 | | case 2: |
124 | 6 | if (keys) { |
125 | 3 | args = [elements[keys[index]], next]; |
126 | | } else { |
127 | 3 | args = [elements[index], next]; |
128 | | } |
129 | 6 | break; |
130 | | case 3: |
131 | 16644 | if (keys) { |
132 | 27 | args = [keys[index], elements[keys[index]], next]; |
133 | | } else { |
134 | 16617 | args = [elements[index], index, next]; |
135 | | } |
136 | 16644 | break; |
137 | | case 4: |
138 | 3 | if (keys) { |
139 | 3 | args = [keys[index], elements[keys[index]], index, next]; |
140 | | } else { |
141 | 0 | return next(new Error('Invalid arguments in item callback')); |
142 | | } |
143 | 3 | break; |
144 | | default: |
145 | 2 | return next(new Error('Invalid arguments in item callback')); |
146 | | } |
147 | 16659 | emit.apply(null, args); |
148 | | } |
149 | | } catch (e) { |
150 | 1 | if (eacher.readable) { |
151 | 1 | next(e); |
152 | | } |
153 | | } |
154 | | } |
155 | 16624 | return null; |
156 | | }; |
157 | 52 | next = function(err) { |
158 | 16661 | if ((err != null) && err instanceof Error) { |
159 | 13 | errors.push(err); |
160 | | } |
161 | 16661 | eacher.done++; |
162 | 16661 | return run(); |
163 | | }; |
164 | 52 | process.nextTick(run); |
165 | 52 | return eacher; |
166 | | }; |