asyncEach.js
1.59 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
var nextTick = require('std/nextTick')
module.exports = function asyncEach(items, opts) {
var finish = opts.finish
if (!items.length) { return finish(null, []) }
var parallel = opts.parallel
if (parallel === true) { parallel = items.length }
if (!parallel) { parallel = 1 }
if (parallel > waitingFor) { parallel = waitingFor }
var nextIndex = 0
var result = []
var errorResult = null
var waitingFor = items.length
var context = opts.context || this
var iterator = module.exports.makeIterator(context, opts.iterate)
function processNextItem() {
if (!waitingFor) {
return finish.call(context, null)
}
var iterationIndex = nextIndex
if (iterationIndex == items.length) {
// no more processing to be done - just wait for the remaining parallel requests to finish
return
}
nextIndex += 1
nextTick(function() {
iterator(items[iterationIndex], iterationIndex, iteratorCallback)
})
}
function iteratorCallback(err) {
if (errorResult) { return }
if (err) {
errorResult = err
finish.call(context, err, null)
} else {
waitingFor -= 1
processNextItem()
}
}
// starts `parallel` number of functions processing the array
for (var parallelI=0; parallelI<parallel; parallelI++) {
processNextItem()
}
}
module.exports.makeIterator = function(context, iterate) {
// the given iterator may expect arguments (item + i + next), or just (item + i)
if (iterate.length == 3) {
return function iterator3(item, i, next) {
iterate.call(context, item, i, next)
}
} else {
return function iterator2(item, i, next) {
iterate.call(context, item, next)
}
}
}