forked from mdeforall/atompm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
___do.js
177 lines (168 loc) · 5.13 KB
/
___do.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/* This file is part of AToMPM - A Tool for Multi-Paradigm Modelling
* Copyright 2011 by the AToMPM team and licensed under the LGPL
* See COPYING.lesser and README.md in the root of this project for full details
*/
// Takes an array of actions and runs them all in parallel.
// You can either pass in an array of actions, or several actions
// as function arguments.
// If you pass in an array, then the output will be an array of all the results
// If you pass in separate arguments, then the output will have several arguments.
exports.parallel = function parallel(actions) {
if (!(Object.prototype.toString.call(actions) === '[object Array]')) {
actions = Array.prototype.slice.call(arguments);
var direct = true;
}
return function(callback, errback) {
var results = [],
counter = actions.length;
actions.forEach(function (action, i) {
action(function (result) {
results[i] = result;
counter--;
if (counter <= 0) {
if (direct) {
callback.apply(null, results);
} else {
callback.call(null, results);
}
}
}, errback);
});
};
};
// Chains together several actions feeding the output of the first to the
// input of the second and the final output to the callback
exports.chain = function chain(actions) {
if (!(Object.prototype.toString.call(actions) === '[object Array]')) {
actions = Array.prototype.slice.call(arguments);
}
return function(callback, errback) {
var pos = 0;
var length = actions.length;
function loop(result) {
pos++;
if (pos >= length) {
callback(result);
} else {
actions[pos](result)(loop, errback);
}
}
actions[pos](loop, errback);
};
};
// Takes an array and does an array map over it using the async callback `fn`
// The signature of `fn` is `function fn(item, callback, errback)`
exports.map = function map(array, fn) {
return function (callback, errback) {
var counter = array.length;
var new_array = [];
array.forEach(function (item, index) {
var local_callback = function (result) {
new_array[index] = result;
counter--;
if (counter <= 0) {
new_array.length = array.length;
callback(new_array);
}
};
var cont = fn(item, local_callback, errback);
if (typeof cont === 'function') {
cont(local_callback, errback);
}
});
};
};
// Takes an array and does an array filter over it using the async callback `fn`
// The signature of `fn` is `function fn(item, callback, errback)`
exports.filter = function filter(array, fn) { return function (callback, errback) {
var counter = array.length;
var valid = {};
array.forEach(function (item, index) {
var local_callback = function (result) {
valid[index] = result;
counter--;
if (counter <= 0) {
var result = [];
array.forEach(function (item, index) {
if (valid[index]) {
result.push(item);
}
});
callback(result);
}
};
var cont = fn(item, local_callback, errback);
if (typeof cont === 'function') {
cont(local_callback, errback);
}
});
};
};
// Takes an array and does a combined filter and map over it. If the result
// of an item is undefined, then it's filtered out, otherwise it's mapped in.
// The signature of `fn` is `function fn(item, callback, errback)`
exports.filterMap = function filterMap(array, fn) { return function (callback, errback) {
var counter = array.length;
var new_array = [];
array.forEach(function (item, index) {
var local_callback = function (result) {
new_array[index] = result;
counter--;
if (counter <= 0) {
new_array.length = array.length;
callback(new_array.filter(function (item) {
return typeof item !== 'undefined';
}));
}
};
var cont = fn(item, local_callback, errback);
if (typeof cont === 'function') {
cont(local_callback, errback);
}
});
};
};
// Allows to group several callbacks.
// exports.combo = function combo(callback) {
// var items = 0,
// results = [];
// function add() {
// var id = items;
// items++;
// return function () {
// check(id, arguments);
// };
// }
// function check(id, arguments) {
// results[id] = Array.prototype.slice.call(arguments);
// items--;
// if (items == 0) {
// callback.apply(this, results);
// }
// }
// return { add: add, check: check };
// }
// Takes any async lib that uses callback based signatures and converts
// the specified names to continuable style and returns the new library.
exports.convert = function (lib, names) {
var newlib = {};
Object.keys(lib).forEach(function (key) {
if (names.indexOf(key) < 0) {
return newlib[key] = lib[key];
}
newlib[key] = function () {
var args = Array.prototype.slice.call(arguments);
return function (callback, errback) {
args.push(function (err, val) {
if (err) {
errback(err);
} else {
callback(val);
}
});
lib[key].apply(lib, args);
};
};
});
return newlib;
};