blob: ccf345f3c7815e92fba01ec2dfc154cc3c3bc426 [file] [log] [blame]
/*
usage:
// do something to a list of things
asyncMap(myListOfStuff, function (thing, cb) { doSomething(thing.foo, cb) }, cb)
// do more than one thing to each item
asyncMap(list, fooFn, barFn, cb)
*/
module.exports = asyncMap
function asyncMap () {
var steps = Array.prototype.slice.call(arguments)
, list = steps.shift() || []
, cb_ = steps.pop()
if (typeof cb_ !== "function") throw new Error(
"No callback provided to asyncMap")
if (!list) return cb_(null, [])
if (!Array.isArray(list)) list = [list]
var n = steps.length
, data = [] // 2d array
, errState = null
, l = list.length
, a = l * n
if (!a) return cb_(null, [])
function cb (er) {
if (er && !errState) errState = er
var argLen = arguments.length
for (var i = 1; i < argLen; i ++) if (arguments[i] !== undefined) {
data[i - 1] = (data[i - 1] || []).concat(arguments[i])
}
// see if any new things have been added.
if (list.length > l) {
var newList = list.slice(l)
a += (list.length - l) * n
l = list.length
process.nextTick(function () {
newList.forEach(function (ar) {
steps.forEach(function (fn) { fn(ar, cb) })
})
})
}
if (--a === 0) cb_.apply(null, [errState].concat(data))
}
// expect the supplied cb function to be called
// "n" times for each thing in the array.
list.forEach(function (ar) {
steps.forEach(function (fn) { fn(ar, cb) })
})
}