/
util.js
111 lines (101 loc) · 2.8 KB
/
util.js
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
var makeArray = Function.prototype.call.bind(Array.prototype.slice)
var util = module.exports = {
makeArray: makeArray
, isFunc: isFunc
, defer: defer
, pushAll: Function.prototype.apply.bind(Array.prototype.push)
, merge: function() {
if (!arguments.length) throw TypeError("Destination object needed")
var sources = makeArray(arguments)
, dest = sources.shift()
sources.forEach(function(source) {
for (var i in source) this[i] = source[i]
}, dest)
return dest
}
, inherits: function(klass, super) {
klass.prototype = Object.create(super.prototype)
}
, def: function(dest, source) {
if (arguments.length < 2) throw TypeError("Wrong number of arguments")
var props = Object.getOwnPropertyNames(source)
props.forEach(function(prop) {
var pd = Object.getOwnPropertyDescriptor(source, prop)
Object.defineProperty(this, prop, pd)
}, dest)
}
}
util.async = {
serial: function(actions, cb) {
actions = makeArray(actions)
actions.forEach(function(action) {
if (typeof action != "function") throw TypeError("An action is not callable")
})
actions.push(function(err) {
var results = makeArray(arguments, 1).reverse()
err = err instanceof Error ? err : null
cb && cb(err, results)
})
defer(chainIter, [actions, []])
}
, map: function(array, action, cb) {
var array = array.slice()
defer(mapIter, [array, action, [], cb])
}
, paraMap: function(array, action, cb) {
if (!array.length) return cb && cb(null, [])
var results = []
, latestErr = null
, num = 0
array.map(function(val, key) {
num++
function innerCallback(err, data) {
latestErr = err
results[key] = data || err
if (!--num) cb && cb(latestErr, results)
}
action.call(innerCallback, val)
})
}
, chain: function() {
var actions = makeArray(arguments)
process.nextTick(function() {
chainIter(actions, [])
})
}
}
function chainIter(actions, initial) {
var action = actions.shift()
if (!action) return
function innerCallback() {
initial.shift()
var recent = makeArray(arguments)
, passingOn = recent.concat(initial)
chainIter(actions, passingOn)
}
action.apply(innerCallback, initial)
}
function mapIter(array, action, results, cb) {
if (!array.length) {
cb && cb(null, results)
return
}
action.call(innerCallback, array.shift())
function innerCallback(err, data) {
if (err) {
cb && cb(err, results)
return
}
results.push(data)
mapIter(array, action, results, cb)
}
}
function defer(fn, args) {
if (!isFunc(fn)) throw TypeError("Not a callable object")
process.nextTick(function() {
fn.apply(null, args)
})
}
function isFunc(obj) {
return Object.prototype.toString.call(obj) == "[object Function]"
}