1 | (function(){
|
2 |
|
3 | var async = {};
|
4 |
|
5 |
|
6 | var root = this;
|
7 | var previous_async = root.async;
|
8 |
|
9 | if(typeof module !== 'undefined' && module.exports) module.exports = async;
|
10 | else root.async = async;
|
11 |
|
12 | async.noConflict = function(){
|
13 | root.async = previous_async;
|
14 | return async;
|
15 | };
|
16 |
|
17 |
|
18 |
|
19 | var _forEach = function(arr, iterator){
|
20 | if(arr.forEach) return arr.forEach(iterator);
|
21 | for(var i=0; i<arr.length; i++){
|
22 | iterator(arr[i], i, arr);
|
23 | }
|
24 | };
|
25 |
|
26 | var _map = function(arr, iterator){
|
27 | if(arr.map) return arr.map(iterator);
|
28 | var results = [];
|
29 | _forEach(arr, function(x, i, a){
|
30 | results.push(iterator(x, i, a));
|
31 | })
|
32 | return results;
|
33 | };
|
34 |
|
35 | var _reduce = function(arr, iterator, memo){
|
36 | if(arr.reduce) return arr.reduce(iterator, memo);
|
37 | _forEach(arr, function(x, i, a){
|
38 | memo = iterator(memo, x, i, a);
|
39 | });
|
40 | return memo;
|
41 | };
|
42 |
|
43 | var _keys = function(obj){
|
44 | if(Object.keys) return Object.keys(obj);
|
45 | var keys = [];
|
46 | for(var k in obj){
|
47 | if(obj.hasOwnProperty(k)) keys.push(k);
|
48 | }
|
49 | return keys;
|
50 | };
|
51 |
|
52 | var _indexOf = function(arr, item){
|
53 | if(arr.indexOf) return arr.indexOf(item);
|
54 | for(var i=0; i<arr.length; i++){
|
55 | if(arr[i] === item) return i;
|
56 | }
|
57 | return -1;
|
58 | };
|
59 |
|
60 |
|
61 |
|
62 |
|
63 | async.nextTick = function(fn){
|
64 | if(typeof process == 'undefined' || !(process.nextTick)){
|
65 | setTimeout(fn, 0);
|
66 | }
|
67 | else process.nextTick(fn);
|
68 | };
|
69 |
|
70 | async.forEach = function(arr, iterator, callback){
|
71 | if(!arr.length) return callback();
|
72 | var completed = 0;
|
73 | _forEach(arr, function(x){
|
74 | iterator(x, function(err){
|
75 | if(err){
|
76 | callback(err);
|
77 | callback = function(){};
|
78 | }
|
79 | else {
|
80 | completed++;
|
81 | if(completed == arr.length) callback();
|
82 | }
|
83 | });
|
84 | });
|
85 | };
|
86 |
|
87 | async.forEachSeries = function(arr, iterator, callback){
|
88 | if(!arr.length) return callback();
|
89 | var completed = 0;
|
90 | var iterate = function(){
|
91 | iterator(arr[completed], function(err){
|
92 | if(err){
|
93 | callback(err);
|
94 | callback = function(){};
|
95 | }
|
96 | else {
|
97 | completed++;
|
98 | if(completed == arr.length) callback();
|
99 | else iterate();
|
100 | }
|
101 | });
|
102 | };
|
103 | iterate();
|
104 | };
|
105 |
|
106 |
|
107 | var doParallel = function(fn){
|
108 | return function(){
|
109 | var args = Array.prototype.slice.call(arguments);
|
110 | return fn.apply(null, [async.forEach].concat(args));
|
111 | };
|
112 | };
|
113 | var doSeries = function(fn){
|
114 | return function(){
|
115 | var args = Array.prototype.slice.call(arguments);
|
116 | return fn.apply(null, [async.forEachSeries].concat(args));
|
117 | };
|
118 | };
|
119 |
|
120 |
|
121 | var _asyncMap = function(eachfn, arr, iterator, callback){
|
122 | var results = [];
|
123 | arr = _map(arr, function(x, i){
|
124 | return {index: i, value: x};
|
125 | });
|
126 | eachfn(arr, function(x, callback){
|
127 | iterator(x.value, function(err, v){
|
128 | results[x.index] = v;
|
129 | callback(err);
|
130 | });
|
131 | }, function(err){
|
132 | callback(err, results);
|
133 | });
|
134 | };
|
135 | async.map = doParallel(_asyncMap);
|
136 | async.mapSeries = doSeries(_asyncMap);
|
137 |
|
138 |
|
139 |
|
140 |
|
141 | async.reduce = function(arr, memo, iterator, callback){
|
142 | async.forEachSeries(arr, function(x, callback){
|
143 | iterator(memo, x, function(err, v){
|
144 | memo = v;
|
145 | callback(err);
|
146 | });
|
147 | }, function(err){
|
148 | callback(err, memo);
|
149 | });
|
150 | };
|
151 |
|
152 | async.inject = async.reduce;
|
153 |
|
154 | async.foldl = async.reduce;
|
155 |
|
156 | async.reduceRight = function(arr, memo, iterator, callback){
|
157 | var reversed = _map(arr, function(x){return x;}).reverse();
|
158 | async.reduce(reversed, memo, iterator, callback);
|
159 | };
|
160 |
|
161 | async.foldr = async.reduceRight;
|
162 |
|
163 | var _filter = function(eachfn, arr, iterator, callback){
|
164 | var results = [];
|
165 | arr = _map(arr, function(x, i){
|
166 | return {index: i, value: x};
|
167 | });
|
168 | eachfn(arr, function(x, callback){
|
169 | iterator(x.value, function(v){
|
170 | if(v) results.push(x);
|
171 | callback();
|
172 | });
|
173 | }, function(err){
|
174 | callback(_map(results.sort(function(a,b){
|
175 | return a.index - b.index;
|
176 | }), function(x){
|
177 | return x.value;
|
178 | }));
|
179 | });
|
180 | };
|
181 | async.filter = doParallel(_filter);
|
182 | async.filterSeries = doSeries(_filter);
|
183 |
|
184 | async.select = async.filter;
|
185 | async.selectSeries = async.filterSeries;
|
186 |
|
187 | var _reject = function(eachfn, arr, iterator, callback){
|
188 | var results = [];
|
189 | arr = _map(arr, function(x, i){
|
190 | return {index: i, value: x};
|
191 | });
|
192 | eachfn(arr, function(x, callback){
|
193 | iterator(x.value, function(v){
|
194 | if(!v) results.push(x);
|
195 | callback();
|
196 | });
|
197 | }, function(err){
|
198 | callback(_map(results.sort(function(a,b){
|
199 | return a.index - b.index;
|
200 | }), function(x){
|
201 | return x.value;
|
202 | }));
|
203 | });
|
204 | };
|
205 | async.reject = doParallel(_reject);
|
206 | async.rejectSeries = doSeries(_reject);
|
207 |
|
208 | var _detect = function(eachfn, arr, iterator, main_callback){
|
209 | eachfn(arr, function(x, callback){
|
210 | iterator(x, function(result){
|
211 | if(result) main_callback(x);
|
212 | else callback();
|
213 | });
|
214 | }, function(err){
|
215 | main_callback();
|
216 | });
|
217 | };
|
218 | async.detect = doParallel(_detect);
|
219 | async.detectSeries = doSeries(_detect);
|
220 |
|
221 | async.some = function(arr, iterator, main_callback){
|
222 | async.forEach(arr, function(x, callback){
|
223 | iterator(x, function(v){
|
224 | if(v){
|
225 | main_callback(true);
|
226 | main_callback = function(){};
|
227 | }
|
228 | callback();
|
229 | });
|
230 | }, function(err){
|
231 | main_callback(false);
|
232 | });
|
233 | };
|
234 |
|
235 | async.any = async.some;
|
236 |
|
237 | async.every = function(arr, iterator, main_callback){
|
238 | async.forEach(arr, function(x, callback){
|
239 | iterator(x, function(v){
|
240 | if(!v){
|
241 | main_callback(false);
|
242 | main_callback = function(){};
|
243 | }
|
244 | callback();
|
245 | });
|
246 | }, function(err){
|
247 | main_callback(true);
|
248 | });
|
249 | };
|
250 |
|
251 | async.all = async.every;
|
252 |
|
253 | async.sortBy = function(arr, iterator, callback){
|
254 | async.map(arr, function(x, callback){
|
255 | iterator(x, function(err, criteria){
|
256 | if(err) callback(err);
|
257 | else callback(null, {value: x, criteria: criteria});
|
258 | });
|
259 | }, function(err, results){
|
260 | if(err) return callback(err);
|
261 | else callback(null, _map(results.sort(function(left, right){
|
262 | var a = left.criteria, b = right.criteria;
|
263 | return a < b ? -1 : a > b ? 1 : 0;
|
264 | }), function(x){return x.value;}));
|
265 | })
|
266 | };
|
267 |
|
268 | async.auto = function(tasks, callback){
|
269 | callback = callback || function(){};
|
270 | var keys = _keys(tasks);
|
271 | if(!keys.length) return callback(null);
|
272 |
|
273 | var completed = [];
|
274 |
|
275 | var listeners = [];
|
276 | var addListener = function(fn){
|
277 | listeners.unshift(fn);
|
278 | };
|
279 | var removeListener = function(fn){
|
280 | for(var i=0; i<listeners.length; i++){
|
281 | if(listeners[i] === fn){
|
282 | listeners.splice(i, 1);
|
283 | return;
|
284 | }
|
285 | }
|
286 | };
|
287 | var taskComplete = function(){
|
288 | _forEach(listeners, function(fn){fn();});
|
289 | };
|
290 |
|
291 | addListener(function(){
|
292 | if(completed.length == keys.length){
|
293 | callback(null);
|
294 | }
|
295 | });
|
296 |
|
297 | _forEach(keys, function(k){
|
298 | var task = (tasks[k] instanceof Function)? [tasks[k]]: tasks[k];
|
299 | var taskCallback = function(err){
|
300 | if(err){
|
301 | callback(err);
|
302 |
|
303 | callback = function(){};
|
304 | }
|
305 | else {
|
306 | completed.push(k);
|
307 | taskComplete();
|
308 | }
|
309 | };
|
310 | var requires = task.slice(0, Math.abs(task.length-1)) || [];
|
311 | var ready = function(){
|
312 | return _reduce(requires, function(a,x){
|
313 | return (a && _indexOf(completed, x) != -1);
|
314 | }, true);
|
315 | };
|
316 | if(ready()) task[task.length-1](taskCallback);
|
317 | else {
|
318 | var listener = function(){
|
319 | if(ready()){
|
320 | removeListener(listener);
|
321 | task[task.length-1](taskCallback);
|
322 | }
|
323 | };
|
324 | addListener(listener);
|
325 | }
|
326 | });
|
327 | };
|
328 |
|
329 | async.waterfall = function(tasks, callback){
|
330 | if(!tasks.length) return callback();
|
331 | callback = callback || function(){};
|
332 | var wrapIterator = function(iterator){
|
333 | return function(err){
|
334 | if(err){
|
335 | callback(err);
|
336 | callback = function(){};
|
337 | }
|
338 | else {
|
339 | var args = Array.prototype.slice.call(arguments, 1);
|
340 | var next = iterator.next();
|
341 | if(next) args.push(wrapIterator(next));
|
342 | else args.push(callback);
|
343 | async.nextTick(function(){iterator.apply(null, args);});
|
344 | }
|
345 | };
|
346 | };
|
347 | wrapIterator(async.iterator(tasks))();
|
348 | };
|
349 |
|
350 | async.parallel = function(tasks, callback){
|
351 | callback = callback || function(){};
|
352 | if (tasks.constructor === Array) {
|
353 | async.map(tasks, function(fn, callback){
|
354 | if(fn){
|
355 | fn(function(err){
|
356 | var args = Array.prototype.slice.call(arguments,1);
|
357 | if(args.length <= 1) args = args[0];
|
358 | callback.call(null, err, args || null);
|
359 | });
|
360 | }
|
361 | }, callback);
|
362 | }
|
363 | else {
|
364 | var results = {};
|
365 | async.forEach(_keys(tasks), function (k, callback) {
|
366 | tasks[k](function (err) {
|
367 | var args = Array.prototype.slice.call(arguments,1);
|
368 | if(args.length <= 1) args = args[0];
|
369 | results[k] = args;
|
370 | callback(err);
|
371 | });
|
372 | }, function (err) {
|
373 | callback(err, results);
|
374 | });
|
375 | }
|
376 | };
|
377 |
|
378 | async.series = function(tasks, callback){
|
379 | callback = callback || function(){};
|
380 | if (tasks.constructor === Array) {
|
381 | async.mapSeries(tasks, function(fn, callback){
|
382 | if(fn){
|
383 | fn(function(err){
|
384 | var args = Array.prototype.slice.call(arguments,1);
|
385 | if(args.length <= 1) args = args[0];
|
386 | callback.call(null, err, args || null);
|
387 | });
|
388 | }
|
389 | }, callback);
|
390 | }
|
391 | else {
|
392 | var results = {};
|
393 | async.forEachSeries(_keys(tasks), function (k, callback) {
|
394 | tasks[k](function (err) {
|
395 | var args = Array.prototype.slice.call(arguments,1);
|
396 | if(args.length <= 1) args = args[0];
|
397 | results[k] = args;
|
398 | callback(err);
|
399 | });
|
400 | }, function (err) {
|
401 | callback(err, results);
|
402 | });
|
403 | }
|
404 | };
|
405 |
|
406 | async.iterator = function(tasks){
|
407 | var makeCallback = function(index){
|
408 | var fn = function(){
|
409 | if(tasks.length) tasks[index].apply(null, arguments);
|
410 | return fn.next();
|
411 | };
|
412 | fn.next = function(){
|
413 | return (index < tasks.length-1)? makeCallback(index+1): null;
|
414 | };
|
415 | return fn;
|
416 | };
|
417 | return makeCallback(0);
|
418 | };
|
419 |
|
420 | async.apply = function(fn){
|
421 | var args = Array.prototype.slice.call(arguments, 1);
|
422 | return function(){
|
423 | return fn.apply(
|
424 | null, args.concat(Array.prototype.slice.call(arguments))
|
425 | );
|
426 | };
|
427 | };
|
428 |
|
429 | var _concat = function(eachfn, arr, fn, callback){
|
430 | var r = [];
|
431 | eachfn(arr, function(x, cb){
|
432 | fn(x, function(err, y){
|
433 | r = r.concat(y || []);
|
434 | cb(err);
|
435 | });
|
436 | }, function(err){
|
437 | callback(err, r);
|
438 | });
|
439 | };
|
440 | async.concat = doParallel(_concat);
|
441 | async.concatSeries = doSeries(_concat);
|
442 |
|
443 | async.whilst = function(test, iterator, callback){
|
444 | if (test()) {
|
445 | iterator(function (err) {
|
446 | if (err) return callback(err);
|
447 | async.whilst(test, iterator, callback);
|
448 | });
|
449 | }
|
450 | else callback();
|
451 | };
|
452 |
|
453 | async.until = function(test, iterator, callback){
|
454 | if (!test()) {
|
455 | iterator(function (err) {
|
456 | if (err) return callback(err);
|
457 | async.until(test, iterator, callback);
|
458 | });
|
459 | }
|
460 | else callback();
|
461 | };
|
462 |
|
463 | var _console_fn = function(name){
|
464 | return function(fn){
|
465 | var args = Array.prototype.slice.call(arguments, 1);
|
466 | fn.apply(null, args.concat([function(err){
|
467 | var args = Array.prototype.slice.call(arguments, 1);
|
468 | if(typeof console != 'undefined'){
|
469 | if(err){
|
470 | if(console.error) console.error(err);
|
471 | }
|
472 | else if(console[name]){
|
473 | _forEach(args, function(x){console[name](x);});
|
474 | }
|
475 | }
|
476 | }]));
|
477 | };
|
478 | };
|
479 | async.log = _console_fn('log');
|
480 | async.dir = _console_fn('dir');
|
481 | |
482 |
|
483 |
|
484 |
|
485 | })();
|