Skip to content
Permalink
Newer
Older
100644 807 lines (737 sloc) 24.4 KB
Nov 17, 2010
1
/*global setTimeout: false, console: false */
2
(function () {
Aug 2, 2010
3
4
var async = {};
5
6
// global on the server, window in the browser
Nov 17, 2010
7
var root = this,
8
previous_async = root.async;
Aug 2, 2010
9
Nov 17, 2010
10
if (typeof module !== 'undefined' && module.exports) {
11
module.exports = async;
12
}
13
else {
14
root.async = async;
15
}
Aug 2, 2010
16
Nov 17, 2010
17
async.noConflict = function () {
Aug 2, 2010
18
root.async = previous_async;
19
return async;
20
};
Jul 7, 2010
22
//// cross-browser compatiblity functions ////
Nov 17, 2010
24
var _forEach = function (arr, iterator) {
25
if (arr.forEach) {
26
return arr.forEach(iterator);
27
}
28
for (var i = 0; i < arr.length; i += 1) {
Jul 7, 2010
29
iterator(arr[i], i, arr);
30
}
31
};
32
Nov 17, 2010
33
var _map = function (arr, iterator) {
34
if (arr.map) {
35
return arr.map(iterator);
36
}
Jul 7, 2010
37
var results = [];
Nov 17, 2010
38
_forEach(arr, function (x, i, a) {
Jul 7, 2010
39
results.push(iterator(x, i, a));
Nov 17, 2010
40
});
Jul 7, 2010
41
return results;
42
};
43
Nov 17, 2010
44
var _reduce = function (arr, iterator, memo) {
45
if (arr.reduce) {
46
return arr.reduce(iterator, memo);
47
}
48
_forEach(arr, function (x, i, a) {
Jul 7, 2010
49
memo = iterator(memo, x, i, a);
Jul 7, 2010
51
return memo;
52
};
53
Nov 17, 2010
54
var _keys = function (obj) {
55
if (Object.keys) {
56
return Object.keys(obj);
57
}
Jul 7, 2010
58
var keys = [];
Nov 17, 2010
59
for (var k in obj) {
60
if (obj.hasOwnProperty(k)) {
61
keys.push(k);
62
}
Jul 7, 2010
63
}
64
return keys;
65
};
66
67
//// exported async module functions ////
Jul 7, 2010
68
69
//// nextTick implementation with browser-compatible fallback ////
70
if (typeof process === 'undefined' || !(process.nextTick)) {
71
async.nextTick = function (fn) {
Jul 7, 2010
72
setTimeout(fn, 0);
73
};
74
}
75
else {
76
async.nextTick = process.nextTick;
77
}
Jul 7, 2010
78
Nov 17, 2010
79
async.forEach = function (arr, iterator, callback) {
80
callback = callback || function () {};
Nov 17, 2010
81
if (!arr.length) {
82
return callback();
83
}
Jul 7, 2010
84
var completed = 0;
Nov 17, 2010
85
_forEach(arr, function (x) {
86
iterator(x, function (err) {
87
if (err) {
Jul 7, 2010
88
callback(err);
Nov 17, 2010
89
callback = function () {};
Jul 7, 2010
90
}
91
else {
Nov 17, 2010
92
completed += 1;
93
if (completed === arr.length) {
94
callback();
95
}
Jul 7, 2010
96
}
97
});
98
});
99
};
100
Nov 17, 2010
101
async.forEachSeries = function (arr, iterator, callback) {
102
callback = callback || function () {};
Nov 17, 2010
103
if (!arr.length) {
104
return callback();
105
}
Jul 7, 2010
106
var completed = 0;
Nov 17, 2010
107
var iterate = function () {
108
iterator(arr[completed], function (err) {
109
if (err) {
Jul 7, 2010
110
callback(err);
Nov 17, 2010
111
callback = function () {};
Jul 7, 2010
112
}
113
else {
Nov 17, 2010
114
completed += 1;
115
if (completed === arr.length) {
116
callback();
117
}
118
else {
119
iterate();
120
}
Jul 7, 2010
121
}
122
});
123
};
124
iterate();
125
};
126
127
async.forEachLimit = function (arr, limit, iterator, callback) {
128
callback = callback || function () {};
129
if (!arr.length || limit <= 0) {
130
return callback();
131
}
132
var completed = 0;
133
var started = 0;
134
var running = 0;
135
136
(function replenish () {
137
if (completed === arr.length) {
138
return callback();
139
}
140
141
while (running < limit && started < arr.length) {
142
iterator(arr[started], function (err) {
143
if (err) {
144
callback(err);
145
callback = function () {};
146
}
147
else {
148
completed += 1;
149
running -= 1;
150
if (completed === arr.length) {
151
callback();
152
}
153
else {
154
replenish();
155
}
156
}
157
});
158
started += 1;
159
running += 1;
160
}
161
})();
162
};
Jul 7, 2010
163
164
Nov 17, 2010
165
var doParallel = function (fn) {
166
return function () {
Jul 7, 2010
167
var args = Array.prototype.slice.call(arguments);
Aug 2, 2010
168
return fn.apply(null, [async.forEach].concat(args));
Jul 7, 2010
169
};
170
};
Nov 17, 2010
171
var doSeries = function (fn) {
172
return function () {
Jul 7, 2010
173
var args = Array.prototype.slice.call(arguments);
Aug 2, 2010
174
return fn.apply(null, [async.forEachSeries].concat(args));
Jul 7, 2010
175
};
176
};
177
178
Nov 17, 2010
179
var _asyncMap = function (eachfn, arr, iterator, callback) {
Jul 7, 2010
180
var results = [];
Nov 17, 2010
181
arr = _map(arr, function (x, i) {
Jul 7, 2010
182
return {index: i, value: x};
183
});
Nov 17, 2010
184
eachfn(arr, function (x, callback) {
185
iterator(x.value, function (err, v) {
Jul 7, 2010
186
results[x.index] = v;
Jul 7, 2010
188
});
Nov 17, 2010
189
}, function (err) {
Jul 7, 2010
190
callback(err, results);
Aug 2, 2010
193
async.map = doParallel(_asyncMap);
194
async.mapSeries = doSeries(_asyncMap);
Jul 7, 2010
197
// reduce only has a series version, as doing reduce in parallel won't
198
// work in many situations.
Nov 17, 2010
199
async.reduce = function (arr, memo, iterator, callback) {
200
async.forEachSeries(arr, function (x, callback) {
201
iterator(memo, x, function (err, v) {
Jul 7, 2010
202
memo = v;
203
callback(err);
204
});
Nov 17, 2010
205
}, function (err) {
Jul 7, 2010
206
callback(err, memo);
Jul 7, 2010
208
};
209
// inject alias
Aug 2, 2010
210
async.inject = async.reduce;
Jul 7, 2010
211
// foldl alias
Aug 2, 2010
212
async.foldl = async.reduce;
Jul 7, 2010
213
Nov 17, 2010
214
async.reduceRight = function (arr, memo, iterator, callback) {
215
var reversed = _map(arr, function (x) {
216
return x;
217
}).reverse();
Aug 2, 2010
218
async.reduce(reversed, memo, iterator, callback);
Jul 7, 2010
219
};
220
// foldr alias
Aug 2, 2010
221
async.foldr = async.reduceRight;
Jul 7, 2010
222
Nov 17, 2010
223
var _filter = function (eachfn, arr, iterator, callback) {
Jul 7, 2010
224
var results = [];
Nov 17, 2010
225
arr = _map(arr, function (x, i) {
Jul 7, 2010
226
return {index: i, value: x};
Nov 17, 2010
228
eachfn(arr, function (x, callback) {
229
iterator(x.value, function (v) {
230
if (v) {
231
results.push(x);
232
}
Jul 7, 2010
233
callback();
234
});
Nov 17, 2010
235
}, function (err) {
236
callback(_map(results.sort(function (a, b) {
Jul 7, 2010
237
return a.index - b.index;
Nov 17, 2010
238
}), function (x) {
Jul 7, 2010
239
return x.value;
240
}));
Jul 7, 2010
242
};
Aug 2, 2010
243
async.filter = doParallel(_filter);
244
async.filterSeries = doSeries(_filter);
Jul 7, 2010
245
// select alias
Aug 2, 2010
246
async.select = async.filter;
247
async.selectSeries = async.filterSeries;
Jul 7, 2010
248
Nov 17, 2010
249
var _reject = function (eachfn, arr, iterator, callback) {
Jul 7, 2010
250
var results = [];
Nov 17, 2010
251
arr = _map(arr, function (x, i) {
Jul 7, 2010
252
return {index: i, value: x};
Nov 17, 2010
254
eachfn(arr, function (x, callback) {
255
iterator(x.value, function (v) {
256
if (!v) {
257
results.push(x);
258
}
Jul 7, 2010
259
callback();
260
});
Nov 17, 2010
261
}, function (err) {
262
callback(_map(results.sort(function (a, b) {
Jul 7, 2010
263
return a.index - b.index;
Nov 17, 2010
264
}), function (x) {
Jul 7, 2010
265
return x.value;
266
}));
Jul 7, 2010
268
};
Aug 2, 2010
269
async.reject = doParallel(_reject);
270
async.rejectSeries = doSeries(_reject);
Jul 7, 2010
271
Nov 17, 2010
272
var _detect = function (eachfn, arr, iterator, main_callback) {
273
eachfn(arr, function (x, callback) {
274
iterator(x, function (result) {
275
if (result) {
276
main_callback(x);
277
main_callback = function () {};
Nov 17, 2010
278
}
279
else {
280
callback();
281
}
Jul 7, 2010
282
});
Nov 17, 2010
283
}, function (err) {
Jul 7, 2010
284
main_callback();
Jul 7, 2010
286
};
Aug 2, 2010
287
async.detect = doParallel(_detect);
288
async.detectSeries = doSeries(_detect);
Jul 7, 2010
289
Nov 17, 2010
290
async.some = function (arr, iterator, main_callback) {
291
async.forEach(arr, function (x, callback) {
292
iterator(x, function (v) {
293
if (v) {
Jul 7, 2010
294
main_callback(true);
Nov 17, 2010
295
main_callback = function () {};
Jul 7, 2010
296
}
297
callback();
298
});
Nov 17, 2010
299
}, function (err) {
Jul 7, 2010
300
main_callback(false);
Jul 7, 2010
302
};
303
// any alias
Aug 2, 2010
304
async.any = async.some;
Jul 7, 2010
305
Nov 17, 2010
306
async.every = function (arr, iterator, main_callback) {
307
async.forEach(arr, function (x, callback) {
308
iterator(x, function (v) {
309
if (!v) {
Jul 7, 2010
310
main_callback(false);
Nov 17, 2010
311
main_callback = function () {};
Jul 7, 2010
312
}
313
callback();
314
});
Nov 17, 2010
315
}, function (err) {
Jul 7, 2010
316
main_callback(true);
Jul 7, 2010
318
};
319
// all alias
Aug 2, 2010
320
async.all = async.every;
Nov 17, 2010
322
async.sortBy = function (arr, iterator, callback) {
323
async.map(arr, function (x, callback) {
324
iterator(x, function (err, criteria) {
325
if (err) {
326
callback(err);
327
}
328
else {
329
callback(null, {value: x, criteria: criteria});
330
}
Jul 7, 2010
331
});
Nov 17, 2010
332
}, function (err, results) {
333
if (err) {
334
return callback(err);
335
}
336
else {
337
var fn = function (left, right) {
338
var a = left.criteria, b = right.criteria;
339
return a < b ? -1 : a > b ? 1 : 0;
340
};
341
callback(null, _map(results.sort(fn), function (x) {
342
return x.value;
343
}));
344
}
345
});
Jul 7, 2010
346
};
347
Nov 17, 2010
348
async.auto = function (tasks, callback) {
349
callback = callback || function () {};
Jul 7, 2010
350
var keys = _keys(tasks);
Nov 17, 2010
351
if (!keys.length) {
352
return callback(null);
353
}
Jul 7, 2010
354
Jul 7, 2010
356
357
var listeners = [];
Nov 17, 2010
358
var addListener = function (fn) {
Jul 7, 2010
359
listeners.unshift(fn);
360
};
Nov 17, 2010
361
var removeListener = function (fn) {
362
for (var i = 0; i < listeners.length; i += 1) {
363
if (listeners[i] === fn) {
Jul 7, 2010
364
listeners.splice(i, 1);
365
return;
366
}
367
}
368
};
Nov 17, 2010
369
var taskComplete = function () {
370
_forEach(listeners.slice(0), function (fn) {
Nov 17, 2010
371
fn();
372
});
Jul 7, 2010
374
Nov 17, 2010
375
addListener(function () {
376
if (_keys(results).length === keys.length) {
377
callback(null, results);
Jul 7, 2010
379
}
380
});
381
Nov 17, 2010
382
_forEach(keys, function (k) {
383
var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
384
var taskCallback = function (err) {
385
if (err) {
Jul 7, 2010
386
callback(err);
387
// stop subsequent errors hitting callback multiple times
Nov 17, 2010
388
callback = function () {};
Jul 7, 2010
389
}
390
else {
391
var args = Array.prototype.slice.call(arguments, 1);
392
if (args.length <= 1) {
393
args = args[0];
394
}
395
results[k] = args;
Jul 7, 2010
396
taskComplete();
397
}
398
};
Nov 17, 2010
399
var requires = task.slice(0, Math.abs(task.length - 1)) || [];
400
var ready = function () {
401
return _reduce(requires, function (a, x) {
402
return (a && results.hasOwnProperty(x));
Jul 7, 2010
403
}, true);
404
};
Nov 17, 2010
405
if (ready()) {
406
task[task.length - 1](taskCallback, results);
Nov 17, 2010
407
}
Nov 17, 2010
409
var listener = function () {
410
if (ready()) {
Jul 7, 2010
411
removeListener(listener);
412
task[task.length - 1](taskCallback, results);
Jul 7, 2010
413
}
414
};
415
addListener(listener);
Jul 7, 2010
417
});
418
};
419
Nov 17, 2010
420
async.waterfall = function (tasks, callback) {
Aug 13, 2011
421
callback = callback || function () {};
Nov 17, 2010
422
if (!tasks.length) {
423
return callback();
424
}
425
var wrapIterator = function (iterator) {
426
return function (err) {
427
if (err) {
Jul 7, 2010
428
callback(err);
Nov 17, 2010
429
callback = function () {};
Jul 7, 2010
430
}
431
else {
432
var args = Array.prototype.slice.call(arguments, 1);
433
var next = iterator.next();
Nov 17, 2010
434
if (next) {
435
args.push(wrapIterator(next));
436
}
437
else {
438
args.push(callback);
439
}
440
async.nextTick(function () {
441
iterator.apply(null, args);
442
});
Jul 7, 2010
443
}
444
};
Aug 2, 2010
446
wrapIterator(async.iterator(tasks))();
Jul 7, 2010
448
Nov 17, 2010
449
async.parallel = function (tasks, callback) {
450
callback = callback || function () {};
451
if (tasks.constructor === Array) {
Nov 17, 2010
452
async.map(tasks, function (fn, callback) {
453
if (fn) {
454
fn(function (err) {
455
var args = Array.prototype.slice.call(arguments, 1);
456
if (args.length <= 1) {
457
args = args[0];
458
}
459
callback.call(null, err, args);
460
});
461
}
462
}, callback);
463
}
464
else {
465
var results = {};
466
async.forEach(_keys(tasks), function (k, callback) {
467
tasks[k](function (err) {
Nov 17, 2010
468
var args = Array.prototype.slice.call(arguments, 1);
469
if (args.length <= 1) {
470
args = args[0];
471
}
472
results[k] = args;
473
callback(err);
Jul 7, 2010
474
});
475
}, function (err) {
476
callback(err, results);
477
});
478
}
Jul 6, 2010
480
Nov 17, 2010
481
async.series = function (tasks, callback) {
482
callback = callback || function () {};
483
if (tasks.constructor === Array) {
Nov 17, 2010
484
async.mapSeries(tasks, function (fn, callback) {
485
if (fn) {
486
fn(function (err) {
487
var args = Array.prototype.slice.call(arguments, 1);
488
if (args.length <= 1) {
489
args = args[0];
490
}
491
callback.call(null, err, args);
492
});
493
}
494
}, callback);
495
}
496
else {
497
var results = {};
498
async.forEachSeries(_keys(tasks), function (k, callback) {
499
tasks[k](function (err) {
Nov 17, 2010
500
var args = Array.prototype.slice.call(arguments, 1);
501
if (args.length <= 1) {
502
args = args[0];
503
}
504
results[k] = args;
505
callback(err);
Jul 7, 2010
506
});
507
}, function (err) {
508
callback(err, results);
509
});
510
}
Jul 6, 2010
511
};
Jul 7, 2010
512
Nov 17, 2010
513
async.iterator = function (tasks) {
514
var makeCallback = function (index) {
515
var fn = function () {
516
if (tasks.length) {
517
tasks[index].apply(null, arguments);
518
}
Jul 7, 2010
519
return fn.next();
520
};
Nov 17, 2010
521
fn.next = function () {
522
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
Jul 7, 2010
523
};
524
return fn;
525
};
526
return makeCallback(0);
527
};
528
Nov 17, 2010
529
async.apply = function (fn) {
Jul 7, 2010
530
var args = Array.prototype.slice.call(arguments, 1);
Nov 17, 2010
531
return function () {
532
return fn.apply(
533
null, args.concat(Array.prototype.slice.call(arguments))
534
);
Jul 7, 2010
535
};
536
};
537
Nov 17, 2010
538
var _concat = function (eachfn, arr, fn, callback) {
539
var r = [];
Nov 17, 2010
540
eachfn(arr, function (x, cb) {
541
fn(x, function (err, y) {
542
r = r.concat(y || []);
543
cb(err);
544
});
Nov 17, 2010
545
}, function (err) {
546
callback(err, r);
547
});
548
};
Sep 17, 2010
549
async.concat = doParallel(_concat);
550
async.concatSeries = doSeries(_concat);
551
Nov 17, 2010
552
async.whilst = function (test, iterator, callback) {
Oct 15, 2010
553
if (test()) {
554
iterator(function (err) {
Nov 17, 2010
555
if (err) {
556
return callback(err);
557
}
Oct 15, 2010
558
async.whilst(test, iterator, callback);
559
});
560
}
Nov 17, 2010
561
else {
562
callback();
563
}
Oct 15, 2010
564
};
565
Nov 17, 2010
566
async.until = function (test, iterator, callback) {
Oct 15, 2010
567
if (!test()) {
568
iterator(function (err) {
Nov 17, 2010
569
if (err) {
570
return callback(err);
571
}
Oct 15, 2010
572
async.until(test, iterator, callback);
573
});
574
}
Nov 17, 2010
575
else {
576
callback();
577
}
Oct 15, 2010
578
};
579
Nov 16, 2010
580
async.queue = function (worker, concurrency) {
581
var workers = 0;
582
var q = {
583
tasks: [],
Nov 16, 2010
584
concurrency: concurrency,
585
saturated: null,
586
empty: null,
587
drain: null,
Nov 16, 2010
588
push: function (data, callback) {
589
if(data.constructor !== Array) {
590
data = [data];
591
}
592
_forEach(data, function(task) {
593
q.tasks.push({
594
data: task,
595
callback: typeof callback === 'function' ? callback : null
596
});
597
if (q.saturated && q.tasks.length == concurrency) {
598
q.saturated();
599
}
600
async.nextTick(q.process);
601
});
Nov 16, 2010
602
},
603
process: function () {
604
if (workers < q.concurrency && q.tasks.length) {
605
var task = q.tasks.shift();
606
if(q.empty && q.tasks.length == 0) q.empty();
Nov 17, 2010
607
workers += 1;
Nov 16, 2010
608
worker(task.data, function () {
Nov 17, 2010
609
workers -= 1;
610
if (task.callback) {
611
task.callback.apply(task, arguments);
612
}
613
if(q.drain && q.tasks.length + workers == 0) q.drain();
Nov 16, 2010
614
q.process();
615
});
616
}
617
},
618
length: function () {
619
return q.tasks.length;
620
},
621
running: function () {
622
return workers;
623
},
624
rateLimit: function (timeout) {
625
// mixin the ratelimiter
626
rateLimiter.call(q);
627
// and invoke it
628
q.rateLimit(timeout);
629
630
// return original queue for chaining
631
return q;
Nov 16, 2010
632
}
633
};
Nov 16, 2010
635
return q;
636
};
637
Nov 17, 2010
638
var _console_fn = function (name) {
639
return function (fn) {
640
var args = Array.prototype.slice.call(arguments, 1);
Nov 17, 2010
641
fn.apply(null, args.concat([function (err) {
642
var args = Array.prototype.slice.call(arguments, 1);
Nov 17, 2010
643
if (typeof console !== 'undefined') {
644
if (err) {
645
if (console.error) {
646
console.error(err);
647
}
648
}
Nov 17, 2010
649
else if (console[name]) {
650
_forEach(args, function (x) {
651
console[name](x);
652
});
653
}
654
}
655
}]));
656
};
657
};
Aug 2, 2010
658
async.log = _console_fn('log');
659
async.dir = _console_fn('dir');
660
/*async.info = _console_fn('info');
661
async.warn = _console_fn('warn');
662
async.error = _console_fn('error');*/
Nov 24, 2010
664
async.memoize = function (fn, hasher) {
665
var memo = {};
666
var queues = {};
Nov 24, 2010
667
hasher = hasher || function (x) {
668
return x;
669
};
670
var memoized = function () {
Nov 24, 2010
671
var args = Array.prototype.slice.call(arguments);
672
var callback = args.pop();
673
var key = hasher.apply(null, args);
674
if (key in memo) {
675
callback.apply(null, memo[key]);
676
}
677
else if (key in queues) {
678
queues[key].push(callback);
679
}
Nov 24, 2010
680
else {
681
queues[key] = [callback];
Nov 24, 2010
682
fn.apply(null, args.concat([function () {
683
memo[key] = arguments;
684
var q = queues[key];
685
delete queues[key];
686
for (var i = 0, l = q.length; i < l; i++) {
687
q[i].apply(null, arguments);
688
}
Nov 24, 2010
689
}]));
690
}
691
};
692
memoized.unmemoized = fn;
693
return memoized;
Nov 24, 2010
694
};
695
696
async.unmemoize = function (fn) {
697
return function () {
698
return (fn.unmemoized || fn).apply(null, arguments);
699
}
Nov 24, 2010
700
};
701
702
/**
703
* Add rate limiting capabilities to a queue.
704
* The timeout should indicate the minimum number of milliseconds before
705
* invoking the next item in the queue.
706
* So for a 100/min. rate limit, use (60000 / 100)
707
*
708
* Invoke like
709
* rateLimiter.call(queue);
710
* queue.rateLimit(timeout);
711
*/
712
var rateLimiter = function () {
713
var queue = this;
714
715
// keep the original methods, so we can invoke them later on
716
var _push = queue.push;
717
var _drain = queue.drain;
718
719
// copy the original tasks
720
var internalQueue = queue.tasks.splice(0);
721
queue.tasks = [];
722
723
// number of items that need to finish
724
var toProcess = internalQueue.length;
725
726
// internal state
727
this.$rateLimitTimeout = 0;
728
this.$rateLimitBusy = false;
730
731
// wrapper around push that pushes to our own queue instead of tasks
732
this.push = function (data, callback) {
733
if(data.constructor !== Array) {
734
data = [data];
735
}
736
data.forEach(function (task) {
737
internalQueue.push({ data: task, callback: callback });
738
});
739
740
toProcess += data.length;
741
};
742
743
// kick off the rate limiter
744
this.rateLimit = function (timeout) {
745
this.$rateLimitTimeout = timeout || 1000;
747
};
748
749
// invoke the rate limit implementation with a timeout
750
this.$processNextRateLimited = function () {
751
var self = this;
752
753
self.$rateLimitInterval = setInterval(function () {
754
self.$processNextRateLimitedImpl();
755
}, self.$rateLimitTimeout);
756
};
757
758
// process the next item in our rate limited queue
759
this.$processNextRateLimitedImpl = function () {
760
var self = this;
761
762
// grab next item...
763
// disadvantage of this approach (doing it in the impl) is that the event loop will die
764
// 1 timeout later than required. Might need to fix that one day.
765
var item = internalQueue.shift(0);
766
if (!item) {
767
return;
768
}
769
770
// we're busy
771
self.$rateLimitBusy = true;
772
773
// the 'drain' function can be overwritten at this point,
774
// as we don't have control over when it happens...
775
if (self.drain !== $emptyDrain) {
776
_drain = self.drain;
777
self.drain = $emptyDrain;
778
}
779
780
// invoke original push function of the queue
781
_push(item.data, function () {
782
if (typeof item.callback === "function") {
783
item.callback.apply(this, arguments);
784
}
785
786
toProcess -= 1;
787
788
if (toProcess === 0) {
789
self.$rateLimitBusy = false;
790
791
clearInterval(self.$rateLimitInterval);
792
793
if (typeof _drain === "function") {
794
_drain();
795
}
796
}
797
});
798
};
799
800
var $emptyDrain = function () {};
801
802
// the original drain function of a queue needs to be overwritten
803
// otherwise the user will be flooded with messages
804
this.drain = $emptyDrain;
805
};
Nov 24, 2010
806
Nov 17, 2010
807
}());