Mitch Garnaat

Removing Node.js packages from repo. These should be downloaded via npm.

Showing 51 changed files with 0 additions and 4806 deletions
1 -Copyright (c) 2010-2014 Caolan McMahon
2 -
3 -Permission is hereby granted, free of charge, to any person obtaining a copy
4 -of this software and associated documentation files (the "Software"), to deal
5 -in the Software without restriction, including without limitation the rights
6 -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 -copies of the Software, and to permit persons to whom the Software is
8 -furnished to do so, subject to the following conditions:
9 -
10 -The above copyright notice and this permission notice shall be included in
11 -all copies or substantial portions of the Software.
12 -
13 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 -THE SOFTWARE.
1 -# Async.js
2 -
3 -[![Build Status via Travis CI](https://travis-ci.org/caolan/async.svg?branch=master)](https://travis-ci.org/caolan/async)
4 -
5 -
6 -Async is a utility module which provides straight-forward, powerful functions
7 -for working with asynchronous JavaScript. Although originally designed for
8 -use with [Node.js](http://nodejs.org), it can also be used directly in the
9 -browser. Also supports [component](https://github.com/component/component).
10 -
11 -Async provides around 20 functions that include the usual 'functional'
12 -suspects (`map`, `reduce`, `filter`, `each`…) as well as some common patterns
13 -for asynchronous control flow (`parallel`, `series`, `waterfall`…). All these
14 -functions assume you follow the Node.js convention of providing a single
15 -callback as the last argument of your `async` function.
16 -
17 -
18 -## Quick Examples
19 -
20 -```javascript
21 -async.map(['file1','file2','file3'], fs.stat, function(err, results){
22 - // results is now an array of stats for each file
23 -});
24 -
25 -async.filter(['file1','file2','file3'], fs.exists, function(results){
26 - // results now equals an array of the existing files
27 -});
28 -
29 -async.parallel([
30 - function(){ ... },
31 - function(){ ... }
32 -], callback);
33 -
34 -async.series([
35 - function(){ ... },
36 - function(){ ... }
37 -]);
38 -```
39 -
40 -There are many more functions available so take a look at the docs below for a
41 -full list. This module aims to be comprehensive, so if you feel anything is
42 -missing please create a GitHub issue for it.
43 -
44 -## Common Pitfalls
45 -
46 -### Binding a context to an iterator
47 -
48 -This section is really about `bind`, not about `async`. If you are wondering how to
49 -make `async` execute your iterators in a given context, or are confused as to why
50 -a method of another library isn't working as an iterator, study this example:
51 -
52 -```js
53 -// Here is a simple object with an (unnecessarily roundabout) squaring method
54 -var AsyncSquaringLibrary = {
55 - squareExponent: 2,
56 - square: function(number, callback){
57 - var result = Math.pow(number, this.squareExponent);
58 - setTimeout(function(){
59 - callback(null, result);
60 - }, 200);
61 - }
62 -};
63 -
64 -async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){
65 - // result is [NaN, NaN, NaN]
66 - // This fails because the `this.squareExponent` expression in the square
67 - // function is not evaluated in the context of AsyncSquaringLibrary, and is
68 - // therefore undefined.
69 -});
70 -
71 -async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){
72 - // result is [1, 4, 9]
73 - // With the help of bind we can attach a context to the iterator before
74 - // passing it to async. Now the square function will be executed in its
75 - // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`
76 - // will be as expected.
77 -});
78 -```
79 -
80 -## Download
81 -
82 -The source is available for download from
83 -[GitHub](http://github.com/caolan/async).
84 -Alternatively, you can install using Node Package Manager (`npm`):
85 -
86 - npm install async
87 -
88 -__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed
89 -
90 -## In the Browser
91 -
92 -So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5.
93 -
94 -Usage:
95 -
96 -```html
97 -<script type="text/javascript" src="async.js"></script>
98 -<script type="text/javascript">
99 -
100 - async.map(data, asyncProcess, function(err, results){
101 - alert(results);
102 - });
103 -
104 -</script>
105 -```
106 -
107 -## Documentation
108 -
109 -### Collections
110 -
111 -* [`each`](#each)
112 -* [`eachSeries`](#eachSeries)
113 -* [`eachLimit`](#eachLimit)
114 -* [`map`](#map)
115 -* [`mapSeries`](#mapSeries)
116 -* [`mapLimit`](#mapLimit)
117 -* [`filter`](#filter)
118 -* [`filterSeries`](#filterSeries)
119 -* [`reject`](#reject)
120 -* [`rejectSeries`](#rejectSeries)
121 -* [`reduce`](#reduce)
122 -* [`reduceRight`](#reduceRight)
123 -* [`detect`](#detect)
124 -* [`detectSeries`](#detectSeries)
125 -* [`sortBy`](#sortBy)
126 -* [`some`](#some)
127 -* [`every`](#every)
128 -* [`concat`](#concat)
129 -* [`concatSeries`](#concatSeries)
130 -
131 -### Control Flow
132 -
133 -* [`series`](#seriestasks-callback)
134 -* [`parallel`](#parallel)
135 -* [`parallelLimit`](#parallellimittasks-limit-callback)
136 -* [`whilst`](#whilst)
137 -* [`doWhilst`](#doWhilst)
138 -* [`until`](#until)
139 -* [`doUntil`](#doUntil)
140 -* [`forever`](#forever)
141 -* [`waterfall`](#waterfall)
142 -* [`compose`](#compose)
143 -* [`seq`](#seq)
144 -* [`applyEach`](#applyEach)
145 -* [`applyEachSeries`](#applyEachSeries)
146 -* [`queue`](#queue)
147 -* [`priorityQueue`](#priorityQueue)
148 -* [`cargo`](#cargo)
149 -* [`auto`](#auto)
150 -* [`retry`](#retry)
151 -* [`iterator`](#iterator)
152 -* [`apply`](#apply)
153 -* [`nextTick`](#nextTick)
154 -* [`times`](#times)
155 -* [`timesSeries`](#timesSeries)
156 -
157 -### Utils
158 -
159 -* [`memoize`](#memoize)
160 -* [`unmemoize`](#unmemoize)
161 -* [`log`](#log)
162 -* [`dir`](#dir)
163 -* [`noConflict`](#noConflict)
164 -
165 -
166 -## Collections
167 -
168 -<a name="forEach" />
169 -<a name="each" />
170 -### each(arr, iterator, callback)
171 -
172 -Applies the function `iterator` to each item in `arr`, in parallel.
173 -The `iterator` is called with an item from the list, and a callback for when it
174 -has finished. If the `iterator` passes an error to its `callback`, the main
175 -`callback` (for the `each` function) is immediately called with the error.
176 -
177 -Note, that since this function applies `iterator` to each item in parallel,
178 -there is no guarantee that the iterator functions will complete in order.
179 -
180 -__Arguments__
181 -
182 -* `arr` - An array to iterate over.
183 -* `iterator(item, callback)` - A function to apply to each item in `arr`.
184 - The iterator is passed a `callback(err)` which must be called once it has
185 - completed. If no error has occured, the `callback` should be run without
186 - arguments or with an explicit `null` argument.
187 -* `callback(err)` - A callback which is called when all `iterator` functions
188 - have finished, or an error occurs.
189 -
190 -__Examples__
191 -
192 -
193 -```js
194 -// assuming openFiles is an array of file names and saveFile is a function
195 -// to save the modified contents of that file:
196 -
197 -async.each(openFiles, saveFile, function(err){
198 - // if any of the saves produced an error, err would equal that error
199 -});
200 -```
201 -
202 -```js
203 -// assuming openFiles is an array of file names
204 -
205 -async.each(openFiles, function( file, callback) {
206 -
207 - // Perform operation on file here.
208 - console.log('Processing file ' + file);
209 -
210 - if( file.length > 32 ) {
211 - console.log('This file name is too long');
212 - callback('File name too long');
213 - } else {
214 - // Do work to process file here
215 - console.log('File processed');
216 - callback();
217 - }
218 -}, function(err){
219 - // if any of the file processing produced an error, err would equal that error
220 - if( err ) {
221 - // One of the iterations produced an error.
222 - // All processing will now stop.
223 - console.log('A file failed to process');
224 - } else {
225 - console.log('All files have been processed successfully');
226 - }
227 -});
228 -```
229 -
230 ----------------------------------------
231 -
232 -<a name="forEachSeries" />
233 -<a name="eachSeries" />
234 -### eachSeries(arr, iterator, callback)
235 -
236 -The same as [`each`](#each), only `iterator` is applied to each item in `arr` in
237 -series. The next `iterator` is only called once the current one has completed.
238 -This means the `iterator` functions will complete in order.
239 -
240 -
241 ----------------------------------------
242 -
243 -<a name="forEachLimit" />
244 -<a name="eachLimit" />
245 -### eachLimit(arr, limit, iterator, callback)
246 -
247 -The same as [`each`](#each), only no more than `limit` `iterator`s will be simultaneously
248 -running at any time.
249 -
250 -Note that the items in `arr` are not processed in batches, so there is no guarantee that
251 -the first `limit` `iterator` functions will complete before any others are started.
252 -
253 -__Arguments__
254 -
255 -* `arr` - An array to iterate over.
256 -* `limit` - The maximum number of `iterator`s to run at any time.
257 -* `iterator(item, callback)` - A function to apply to each item in `arr`.
258 - The iterator is passed a `callback(err)` which must be called once it has
259 - completed. If no error has occured, the callback should be run without
260 - arguments or with an explicit `null` argument.
261 -* `callback(err)` - A callback which is called when all `iterator` functions
262 - have finished, or an error occurs.
263 -
264 -__Example__
265 -
266 -```js
267 -// Assume documents is an array of JSON objects and requestApi is a
268 -// function that interacts with a rate-limited REST api.
269 -
270 -async.eachLimit(documents, 20, requestApi, function(err){
271 - // if any of the saves produced an error, err would equal that error
272 -});
273 -```
274 -
275 ----------------------------------------
276 -
277 -<a name="map" />
278 -### map(arr, iterator, callback)
279 -
280 -Produces a new array of values by mapping each value in `arr` through
281 -the `iterator` function. The `iterator` is called with an item from `arr` and a
282 -callback for when it has finished processing. Each of these callback takes 2 arguments:
283 -an `error`, and the transformed item from `arr`. If `iterator` passes an error to this
284 -callback, the main `callback` (for the `map` function) is immediately called with the error.
285 -
286 -Note, that since this function applies the `iterator` to each item in parallel,
287 -there is no guarantee that the `iterator` functions will complete in order.
288 -However, the results array will be in the same order as the original `arr`.
289 -
290 -__Arguments__
291 -
292 -* `arr` - An array to iterate over.
293 -* `iterator(item, callback)` - A function to apply to each item in `arr`.
294 - The iterator is passed a `callback(err, transformed)` which must be called once
295 - it has completed with an error (which can be `null`) and a transformed item.
296 -* `callback(err, results)` - A callback which is called when all `iterator`
297 - functions have finished, or an error occurs. Results is an array of the
298 - transformed items from the `arr`.
299 -
300 -__Example__
301 -
302 -```js
303 -async.map(['file1','file2','file3'], fs.stat, function(err, results){
304 - // results is now an array of stats for each file
305 -});
306 -```
307 -
308 ----------------------------------------
309 -
310 -<a name="mapSeries" />
311 -### mapSeries(arr, iterator, callback)
312 -
313 -The same as [`map`](#map), only the `iterator` is applied to each item in `arr` in
314 -series. The next `iterator` is only called once the current one has completed.
315 -The results array will be in the same order as the original.
316 -
317 -
318 ----------------------------------------
319 -
320 -<a name="mapLimit" />
321 -### mapLimit(arr, limit, iterator, callback)
322 -
323 -The same as [`map`](#map), only no more than `limit` `iterator`s will be simultaneously
324 -running at any time.
325 -
326 -Note that the items are not processed in batches, so there is no guarantee that
327 -the first `limit` `iterator` functions will complete before any others are started.
328 -
329 -__Arguments__
330 -
331 -* `arr` - An array to iterate over.
332 -* `limit` - The maximum number of `iterator`s to run at any time.
333 -* `iterator(item, callback)` - A function to apply to each item in `arr`.
334 - The iterator is passed a `callback(err, transformed)` which must be called once
335 - it has completed with an error (which can be `null`) and a transformed item.
336 -* `callback(err, results)` - A callback which is called when all `iterator`
337 - calls have finished, or an error occurs. The result is an array of the
338 - transformed items from the original `arr`.
339 -
340 -__Example__
341 -
342 -```js
343 -async.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){
344 - // results is now an array of stats for each file
345 -});
346 -```
347 -
348 ----------------------------------------
349 -
350 -<a name="select" />
351 -<a name="filter" />
352 -### filter(arr, iterator, callback)
353 -
354 -__Alias:__ `select`
355 -
356 -Returns a new array of all the values in `arr` which pass an async truth test.
357 -_The callback for each `iterator` call only accepts a single argument of `true` or
358 -`false`; it does not accept an error argument first!_ This is in-line with the
359 -way node libraries work with truth tests like `fs.exists`. This operation is
360 -performed in parallel, but the results array will be in the same order as the
361 -original.
362 -
363 -__Arguments__
364 -
365 -* `arr` - An array to iterate over.
366 -* `iterator(item, callback)` - A truth test to apply to each item in `arr`.
367 - The `iterator` is passed a `callback(truthValue)`, which must be called with a
368 - boolean argument once it has completed.
369 -* `callback(results)` - A callback which is called after all the `iterator`
370 - functions have finished.
371 -
372 -__Example__
373 -
374 -```js
375 -async.filter(['file1','file2','file3'], fs.exists, function(results){
376 - // results now equals an array of the existing files
377 -});
378 -```
379 -
380 ----------------------------------------
381 -
382 -<a name="selectSeries" />
383 -<a name="filterSeries" />
384 -### filterSeries(arr, iterator, callback)
385 -
386 -__Alias:__ `selectSeries`
387 -
388 -The same as [`filter`](#filter) only the `iterator` is applied to each item in `arr` in
389 -series. The next `iterator` is only called once the current one has completed.
390 -The results array will be in the same order as the original.
391 -
392 ----------------------------------------
393 -
394 -<a name="reject" />
395 -### reject(arr, iterator, callback)
396 -
397 -The opposite of [`filter`](#filter). Removes values that pass an `async` truth test.
398 -
399 ----------------------------------------
400 -
401 -<a name="rejectSeries" />
402 -### rejectSeries(arr, iterator, callback)
403 -
404 -The same as [`reject`](#reject), only the `iterator` is applied to each item in `arr`
405 -in series.
406 -
407 -
408 ----------------------------------------
409 -
410 -<a name="reduce" />
411 -### reduce(arr, memo, iterator, callback)
412 -
413 -__Aliases:__ `inject`, `foldl`
414 -
415 -Reduces `arr` into a single value using an async `iterator` to return
416 -each successive step. `memo` is the initial state of the reduction.
417 -This function only operates in series.
418 -
419 -For performance reasons, it may make sense to split a call to this function into
420 -a parallel map, and then use the normal `Array.prototype.reduce` on the results.
421 -This function is for situations where each step in the reduction needs to be async;
422 -if you can get the data before reducing it, then it's probably a good idea to do so.
423 -
424 -__Arguments__
425 -
426 -* `arr` - An array to iterate over.
427 -* `memo` - The initial state of the reduction.
428 -* `iterator(memo, item, callback)` - A function applied to each item in the
429 - array to produce the next step in the reduction. The `iterator` is passed a
430 - `callback(err, reduction)` which accepts an optional error as its first
431 - argument, and the state of the reduction as the second. If an error is
432 - passed to the callback, the reduction is stopped and the main `callback` is
433 - immediately called with the error.
434 -* `callback(err, result)` - A callback which is called after all the `iterator`
435 - functions have finished. Result is the reduced value.
436 -
437 -__Example__
438 -
439 -```js
440 -async.reduce([1,2,3], 0, function(memo, item, callback){
441 - // pointless async:
442 - process.nextTick(function(){
443 - callback(null, memo + item)
444 - });
445 -}, function(err, result){
446 - // result is now equal to the last value of memo, which is 6
447 -});
448 -```
449 -
450 ----------------------------------------
451 -
452 -<a name="reduceRight" />
453 -### reduceRight(arr, memo, iterator, callback)
454 -
455 -__Alias:__ `foldr`
456 -
457 -Same as [`reduce`](#reduce), only operates on `arr` in reverse order.
458 -
459 -
460 ----------------------------------------
461 -
462 -<a name="detect" />
463 -### detect(arr, iterator, callback)
464 -
465 -Returns the first value in `arr` that passes an async truth test. The
466 -`iterator` is applied in parallel, meaning the first iterator to return `true` will
467 -fire the detect `callback` with that result. That means the result might not be
468 -the first item in the original `arr` (in terms of order) that passes the test.
469 -
470 -If order within the original `arr` is important, then look at [`detectSeries`](#detectSeries).
471 -
472 -__Arguments__
473 -
474 -* `arr` - An array to iterate over.
475 -* `iterator(item, callback)` - A truth test to apply to each item in `arr`.
476 - The iterator is passed a `callback(truthValue)` which must be called with a
477 - boolean argument once it has completed.
478 -* `callback(result)` - A callback which is called as soon as any iterator returns
479 - `true`, or after all the `iterator` functions have finished. Result will be
480 - the first item in the array that passes the truth test (iterator) or the
481 - value `undefined` if none passed.
482 -
483 -__Example__
484 -
485 -```js
486 -async.detect(['file1','file2','file3'], fs.exists, function(result){
487 - // result now equals the first file in the list that exists
488 -});
489 -```
490 -
491 ----------------------------------------
492 -
493 -<a name="detectSeries" />
494 -### detectSeries(arr, iterator, callback)
495 -
496 -The same as [`detect`](#detect), only the `iterator` is applied to each item in `arr`
497 -in series. This means the result is always the first in the original `arr` (in
498 -terms of array order) that passes the truth test.
499 -
500 -
501 ----------------------------------------
502 -
503 -<a name="sortBy" />
504 -### sortBy(arr, iterator, callback)
505 -
506 -Sorts a list by the results of running each `arr` value through an async `iterator`.
507 -
508 -__Arguments__
509 -
510 -* `arr` - An array to iterate over.
511 -* `iterator(item, callback)` - A function to apply to each item in `arr`.
512 - The iterator is passed a `callback(err, sortValue)` which must be called once it
513 - has completed with an error (which can be `null`) and a value to use as the sort
514 - criteria.
515 -* `callback(err, results)` - A callback which is called after all the `iterator`
516 - functions have finished, or an error occurs. Results is the items from
517 - the original `arr` sorted by the values returned by the `iterator` calls.
518 -
519 -__Example__
520 -
521 -```js
522 -async.sortBy(['file1','file2','file3'], function(file, callback){
523 - fs.stat(file, function(err, stats){
524 - callback(err, stats.mtime);
525 - });
526 -}, function(err, results){
527 - // results is now the original array of files sorted by
528 - // modified date
529 -});
530 -```
531 -
532 -__Sort Order__
533 -
534 -By modifying the callback parameter the sorting order can be influenced:
535 -
536 -```js
537 -//ascending order
538 -async.sortBy([1,9,3,5], function(x, callback){
539 - callback(err, x);
540 -}, function(err,result){
541 - //result callback
542 -} );
543 -
544 -//descending order
545 -async.sortBy([1,9,3,5], function(x, callback){
546 - callback(err, x*-1); //<- x*-1 instead of x, turns the order around
547 -}, function(err,result){
548 - //result callback
549 -} );
550 -```
551 -
552 ----------------------------------------
553 -
554 -<a name="some" />
555 -### some(arr, iterator, callback)
556 -
557 -__Alias:__ `any`
558 -
559 -Returns `true` if at least one element in the `arr` satisfies an async test.
560 -_The callback for each iterator call only accepts a single argument of `true` or
561 -`false`; it does not accept an error argument first!_ This is in-line with the
562 -way node libraries work with truth tests like `fs.exists`. Once any iterator
563 -call returns `true`, the main `callback` is immediately called.
564 -
565 -__Arguments__
566 -
567 -* `arr` - An array to iterate over.
568 -* `iterator(item, callback)` - A truth test to apply to each item in the array
569 - in parallel. The iterator is passed a callback(truthValue) which must be
570 - called with a boolean argument once it has completed.
571 -* `callback(result)` - A callback which is called as soon as any iterator returns
572 - `true`, or after all the iterator functions have finished. Result will be
573 - either `true` or `false` depending on the values of the async tests.
574 -
575 -__Example__
576 -
577 -```js
578 -async.some(['file1','file2','file3'], fs.exists, function(result){
579 - // if result is true then at least one of the files exists
580 -});
581 -```
582 -
583 ----------------------------------------
584 -
585 -<a name="every" />
586 -### every(arr, iterator, callback)
587 -
588 -__Alias:__ `all`
589 -
590 -Returns `true` if every element in `arr` satisfies an async test.
591 -_The callback for each `iterator` call only accepts a single argument of `true` or
592 -`false`; it does not accept an error argument first!_ This is in-line with the
593 -way node libraries work with truth tests like `fs.exists`.
594 -
595 -__Arguments__
596 -
597 -* `arr` - An array to iterate over.
598 -* `iterator(item, callback)` - A truth test to apply to each item in the array
599 - in parallel. The iterator is passed a callback(truthValue) which must be
600 - called with a boolean argument once it has completed.
601 -* `callback(result)` - A callback which is called after all the `iterator`
602 - functions have finished. Result will be either `true` or `false` depending on
603 - the values of the async tests.
604 -
605 -__Example__
606 -
607 -```js
608 -async.every(['file1','file2','file3'], fs.exists, function(result){
609 - // if result is true then every file exists
610 -});
611 -```
612 -
613 ----------------------------------------
614 -
615 -<a name="concat" />
616 -### concat(arr, iterator, callback)
617 -
618 -Applies `iterator` to each item in `arr`, concatenating the results. Returns the
619 -concatenated list. The `iterator`s are called in parallel, and the results are
620 -concatenated as they return. There is no guarantee that the results array will
621 -be returned in the original order of `arr` passed to the `iterator` function.
622 -
623 -__Arguments__
624 -
625 -* `arr` - An array to iterate over.
626 -* `iterator(item, callback)` - A function to apply to each item in `arr`.
627 - The iterator is passed a `callback(err, results)` which must be called once it
628 - has completed with an error (which can be `null`) and an array of results.
629 -* `callback(err, results)` - A callback which is called after all the `iterator`
630 - functions have finished, or an error occurs. Results is an array containing
631 - the concatenated results of the `iterator` function.
632 -
633 -__Example__
634 -
635 -```js
636 -async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){
637 - // files is now a list of filenames that exist in the 3 directories
638 -});
639 -```
640 -
641 ----------------------------------------
642 -
643 -<a name="concatSeries" />
644 -### concatSeries(arr, iterator, callback)
645 -
646 -Same as [`concat`](#concat), but executes in series instead of parallel.
647 -
648 -
649 -## Control Flow
650 -
651 -<a name="series" />
652 -### series(tasks, [callback])
653 -
654 -Run the functions in the `tasks` array in series, each one running once the previous
655 -function has completed. If any functions in the series pass an error to its
656 -callback, no more functions are run, and `callback` is immediately called with the value of the error.
657 -Otherwise, `callback` receives an array of results when `tasks` have completed.
658 -
659 -It is also possible to use an object instead of an array. Each property will be
660 -run as a function, and the results will be passed to the final `callback` as an object
661 -instead of an array. This can be a more readable way of handling results from
662 -[`series`](#series).
663 -
664 -**Note** that while many implementations preserve the order of object properties, the
665 -[ECMAScript Language Specifcation](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6)
666 -explicitly states that
667 -
668 -> The mechanics and order of enumerating the properties is not specified.
669 -
670 -So if you rely on the order in which your series of functions are executed, and want
671 -this to work on all platforms, consider using an array.
672 -
673 -__Arguments__
674 -
675 -* `tasks` - An array or object containing functions to run, each function is passed
676 - a `callback(err, result)` it must call on completion with an error `err` (which can
677 - be `null`) and an optional `result` value.
678 -* `callback(err, results)` - An optional callback to run once all the functions
679 - have completed. This function gets a results array (or object) containing all
680 - the result arguments passed to the `task` callbacks.
681 -
682 -__Example__
683 -
684 -```js
685 -async.series([
686 - function(callback){
687 - // do some stuff ...
688 - callback(null, 'one');
689 - },
690 - function(callback){
691 - // do some more stuff ...
692 - callback(null, 'two');
693 - }
694 -],
695 -// optional callback
696 -function(err, results){
697 - // results is now equal to ['one', 'two']
698 -});
699 -
700 -
701 -// an example using an object instead of an array
702 -async.series({
703 - one: function(callback){
704 - setTimeout(function(){
705 - callback(null, 1);
706 - }, 200);
707 - },
708 - two: function(callback){
709 - setTimeout(function(){
710 - callback(null, 2);
711 - }, 100);
712 - }
713 -},
714 -function(err, results) {
715 - // results is now equal to: {one: 1, two: 2}
716 -});
717 -```
718 -
719 ----------------------------------------
720 -
721 -<a name="parallel" />
722 -### parallel(tasks, [callback])
723 -
724 -Run the `tasks` array of functions in parallel, without waiting until the previous
725 -function has completed. If any of the functions pass an error to its
726 -callback, the main `callback` is immediately called with the value of the error.
727 -Once the `tasks` have completed, the results are passed to the final `callback` as an
728 -array.
729 -
730 -It is also possible to use an object instead of an array. Each property will be
731 -run as a function and the results will be passed to the final `callback` as an object
732 -instead of an array. This can be a more readable way of handling results from
733 -[`parallel`](#parallel).
734 -
735 -
736 -__Arguments__
737 -
738 -* `tasks` - An array or object containing functions to run. Each function is passed
739 - a `callback(err, result)` which it must call on completion with an error `err`
740 - (which can be `null`) and an optional `result` value.
741 -* `callback(err, results)` - An optional callback to run once all the functions
742 - have completed. This function gets a results array (or object) containing all
743 - the result arguments passed to the task callbacks.
744 -
745 -__Example__
746 -
747 -```js
748 -async.parallel([
749 - function(callback){
750 - setTimeout(function(){
751 - callback(null, 'one');
752 - }, 200);
753 - },
754 - function(callback){
755 - setTimeout(function(){
756 - callback(null, 'two');
757 - }, 100);
758 - }
759 -],
760 -// optional callback
761 -function(err, results){
762 - // the results array will equal ['one','two'] even though
763 - // the second function had a shorter timeout.
764 -});
765 -
766 -
767 -// an example using an object instead of an array
768 -async.parallel({
769 - one: function(callback){
770 - setTimeout(function(){
771 - callback(null, 1);
772 - }, 200);
773 - },
774 - two: function(callback){
775 - setTimeout(function(){
776 - callback(null, 2);
777 - }, 100);
778 - }
779 -},
780 -function(err, results) {
781 - // results is now equals to: {one: 1, two: 2}
782 -});
783 -```
784 -
785 ----------------------------------------
786 -
787 -<a name="parallelLimit" />
788 -### parallelLimit(tasks, limit, [callback])
789 -
790 -The same as [`parallel`](#parallel), only `tasks` are executed in parallel
791 -with a maximum of `limit` tasks executing at any time.
792 -
793 -Note that the `tasks` are not executed in batches, so there is no guarantee that
794 -the first `limit` tasks will complete before any others are started.
795 -
796 -__Arguments__
797 -
798 -* `tasks` - An array or object containing functions to run, each function is passed
799 - a `callback(err, result)` it must call on completion with an error `err` (which can
800 - be `null`) and an optional `result` value.
801 -* `limit` - The maximum number of `tasks` to run at any time.
802 -* `callback(err, results)` - An optional callback to run once all the functions
803 - have completed. This function gets a results array (or object) containing all
804 - the result arguments passed to the `task` callbacks.
805 -
806 ----------------------------------------
807 -
808 -<a name="whilst" />
809 -### whilst(test, fn, callback)
810 -
811 -Repeatedly call `fn`, while `test` returns `true`. Calls `callback` when stopped,
812 -or an error occurs.
813 -
814 -__Arguments__
815 -
816 -* `test()` - synchronous truth test to perform before each execution of `fn`.
817 -* `fn(callback)` - A function which is called each time `test` passes. The function is
818 - passed a `callback(err)`, which must be called once it has completed with an
819 - optional `err` argument.
820 -* `callback(err)` - A callback which is called after the test fails and repeated
821 - execution of `fn` has stopped.
822 -
823 -__Example__
824 -
825 -```js
826 -var count = 0;
827 -
828 -async.whilst(
829 - function () { return count < 5; },
830 - function (callback) {
831 - count++;
832 - setTimeout(callback, 1000);
833 - },
834 - function (err) {
835 - // 5 seconds have passed
836 - }
837 -);
838 -```
839 -
840 ----------------------------------------
841 -
842 -<a name="doWhilst" />
843 -### doWhilst(fn, test, callback)
844 -
845 -The post-check version of [`whilst`](#whilst). To reflect the difference in
846 -the order of operations, the arguments `test` and `fn` are switched.
847 -
848 -`doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
849 -
850 ----------------------------------------
851 -
852 -<a name="until" />
853 -### until(test, fn, callback)
854 -
855 -Repeatedly call `fn` until `test` returns `true`. Calls `callback` when stopped,
856 -or an error occurs.
857 -
858 -The inverse of [`whilst`](#whilst).
859 -
860 ----------------------------------------
861 -
862 -<a name="doUntil" />
863 -### doUntil(fn, test, callback)
864 -
865 -Like [`doWhilst`](#doWhilst), except the `test` is inverted. Note the argument ordering differs from `until`.
866 -
867 ----------------------------------------
868 -
869 -<a name="forever" />
870 -### forever(fn, errback)
871 -
872 -Calls the asynchronous function `fn` with a callback parameter that allows it to
873 -call itself again, in series, indefinitely.
874 -
875 -If an error is passed to the callback then `errback` is called with the
876 -error, and execution stops, otherwise it will never be called.
877 -
878 -```js
879 -async.forever(
880 - function(next) {
881 - // next is suitable for passing to things that need a callback(err [, whatever]);
882 - // it will result in this function being called again.
883 - },
884 - function(err) {
885 - // if next is called with a value in its first parameter, it will appear
886 - // in here as 'err', and execution will stop.
887 - }
888 -);
889 -```
890 -
891 ----------------------------------------
892 -
893 -<a name="waterfall" />
894 -### waterfall(tasks, [callback])
895 -
896 -Runs the `tasks` array of functions in series, each passing their results to the next in
897 -the array. However, if any of the `tasks` pass an error to their own callback, the
898 -next function is not executed, and the main `callback` is immediately called with
899 -the error.
900 -
901 -__Arguments__
902 -
903 -* `tasks` - An array of functions to run, each function is passed a
904 - `callback(err, result1, result2, ...)` it must call on completion. The first
905 - argument is an error (which can be `null`) and any further arguments will be
906 - passed as arguments in order to the next task.
907 -* `callback(err, [results])` - An optional callback to run once all the functions
908 - have completed. This will be passed the results of the last task's callback.
909 -
910 -
911 -
912 -__Example__
913 -
914 -```js
915 -async.waterfall([
916 - function(callback){
917 - callback(null, 'one', 'two');
918 - },
919 - function(arg1, arg2, callback){
920 - // arg1 now equals 'one' and arg2 now equals 'two'
921 - callback(null, 'three');
922 - },
923 - function(arg1, callback){
924 - // arg1 now equals 'three'
925 - callback(null, 'done');
926 - }
927 -], function (err, result) {
928 - // result now equals 'done'
929 -});
930 -```
931 -
932 ----------------------------------------
933 -<a name="compose" />
934 -### compose(fn1, fn2...)
935 -
936 -Creates a function which is a composition of the passed asynchronous
937 -functions. Each function consumes the return value of the function that
938 -follows. Composing functions `f()`, `g()`, and `h()` would produce the result of
939 -`f(g(h()))`, only this version uses callbacks to obtain the return values.
940 -
941 -Each function is executed with the `this` binding of the composed function.
942 -
943 -__Arguments__
944 -
945 -* `functions...` - the asynchronous functions to compose
946 -
947 -
948 -__Example__
949 -
950 -```js
951 -function add1(n, callback) {
952 - setTimeout(function () {
953 - callback(null, n + 1);
954 - }, 10);
955 -}
956 -
957 -function mul3(n, callback) {
958 - setTimeout(function () {
959 - callback(null, n * 3);
960 - }, 10);
961 -}
962 -
963 -var add1mul3 = async.compose(mul3, add1);
964 -
965 -add1mul3(4, function (err, result) {
966 - // result now equals 15
967 -});
968 -```
969 -
970 ----------------------------------------
971 -<a name="seq" />
972 -### seq(fn1, fn2...)
973 -
974 -Version of the compose function that is more natural to read.
975 -Each following function consumes the return value of the latter function.
976 -
977 -Each function is executed with the `this` binding of the composed function.
978 -
979 -__Arguments__
980 -
981 -* functions... - the asynchronous functions to compose
982 -
983 -
984 -__Example__
985 -
986 -```js
987 -// Requires lodash (or underscore), express3 and dresende's orm2.
988 -// Part of an app, that fetches cats of the logged user.
989 -// This example uses `seq` function to avoid overnesting and error
990 -// handling clutter.
991 -app.get('/cats', function(request, response) {
992 - function handleError(err, data, callback) {
993 - if (err) {
994 - console.error(err);
995 - response.json({ status: 'error', message: err.message });
996 - }
997 - else {
998 - callback(data);
999 - }
1000 - }
1001 - var User = request.models.User;
1002 - async.seq(
1003 - _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data))
1004 - handleError,
1005 - function(user, fn) {
1006 - user.getCats(fn); // 'getCats' has signature (callback(err, data))
1007 - },
1008 - handleError,
1009 - function(cats) {
1010 - response.json({ status: 'ok', message: 'Cats found', data: cats });
1011 - }
1012 - )(req.session.user_id);
1013 - }
1014 -});
1015 -```
1016 -
1017 ----------------------------------------
1018 -<a name="applyEach" />
1019 -### applyEach(fns, args..., callback)
1020 -
1021 -Applies the provided arguments to each function in the array, calling
1022 -`callback` after all functions have completed. If you only provide the first
1023 -argument, then it will return a function which lets you pass in the
1024 -arguments as if it were a single function call.
1025 -
1026 -__Arguments__
1027 -
1028 -* `fns` - the asynchronous functions to all call with the same arguments
1029 -* `args...` - any number of separate arguments to pass to the function
1030 -* `callback` - the final argument should be the callback, called when all
1031 - functions have completed processing
1032 -
1033 -
1034 -__Example__
1035 -
1036 -```js
1037 -async.applyEach([enableSearch, updateSchema], 'bucket', callback);
1038 -
1039 -// partial application example:
1040 -async.each(
1041 - buckets,
1042 - async.applyEach([enableSearch, updateSchema]),
1043 - callback
1044 -);
1045 -```
1046 -
1047 ----------------------------------------
1048 -
1049 -<a name="applyEachSeries" />
1050 -### applyEachSeries(arr, iterator, callback)
1051 -
1052 -The same as [`applyEach`](#applyEach) only the functions are applied in series.
1053 -
1054 ----------------------------------------
1055 -
1056 -<a name="queue" />
1057 -### queue(worker, concurrency)
1058 -
1059 -Creates a `queue` object with the specified `concurrency`. Tasks added to the
1060 -`queue` are processed in parallel (up to the `concurrency` limit). If all
1061 -`worker`s are in progress, the task is queued until one becomes available.
1062 -Once a `worker` completes a `task`, that `task`'s callback is called.
1063 -
1064 -__Arguments__
1065 -
1066 -* `worker(task, callback)` - An asynchronous function for processing a queued
1067 - task, which must call its `callback(err)` argument when finished, with an
1068 - optional `error` as an argument.
1069 -* `concurrency` - An `integer` for determining how many `worker` functions should be
1070 - run in parallel.
1071 -
1072 -__Queue objects__
1073 -
1074 -The `queue` object returned by this function has the following properties and
1075 -methods:
1076 -
1077 -* `length()` - a function returning the number of items waiting to be processed.
1078 -* `started` - a function returning whether or not any items have been pushed and processed by the queue
1079 -* `running()` - a function returning the number of items currently being processed.
1080 -* `idle()` - a function returning false if there are items waiting or being processed, or true if not.
1081 -* `concurrency` - an integer for determining how many `worker` functions should be
1082 - run in parallel. This property can be changed after a `queue` is created to
1083 - alter the concurrency on-the-fly.
1084 -* `push(task, [callback])` - add a new task to the `queue`. Calls `callback` once
1085 - the `worker` has finished processing the task. Instead of a single task, a `tasks` array
1086 - can be submitted. The respective callback is used for every task in the list.
1087 -* `unshift(task, [callback])` - add a new task to the front of the `queue`.
1088 -* `saturated` - a callback that is called when the `queue` length hits the `concurrency` limit,
1089 - and further tasks will be queued.
1090 -* `empty` - a callback that is called when the last item from the `queue` is given to a `worker`.
1091 -* `drain` - a callback that is called when the last item from the `queue` has returned from the `worker`.
1092 -* `paused` - a boolean for determining whether the queue is in a paused state
1093 -* `pause()` - a function that pauses the processing of tasks until `resume()` is called.
1094 -* `resume()` - a function that resumes the processing of queued tasks when the queue is paused.
1095 -* `kill()` - a function that empties remaining tasks from the queue forcing it to go idle.
1096 -
1097 -__Example__
1098 -
1099 -```js
1100 -// create a queue object with concurrency 2
1101 -
1102 -var q = async.queue(function (task, callback) {
1103 - console.log('hello ' + task.name);
1104 - callback();
1105 -}, 2);
1106 -
1107 -
1108 -// assign a callback
1109 -q.drain = function() {
1110 - console.log('all items have been processed');
1111 -}
1112 -
1113 -// add some items to the queue
1114 -
1115 -q.push({name: 'foo'}, function (err) {
1116 - console.log('finished processing foo');
1117 -});
1118 -q.push({name: 'bar'}, function (err) {
1119 - console.log('finished processing bar');
1120 -});
1121 -
1122 -// add some items to the queue (batch-wise)
1123 -
1124 -q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {
1125 - console.log('finished processing bar');
1126 -});
1127 -
1128 -// add some items to the front of the queue
1129 -
1130 -q.unshift({name: 'bar'}, function (err) {
1131 - console.log('finished processing bar');
1132 -});
1133 -```
1134 -
1135 -
1136 ----------------------------------------
1137 -
1138 -<a name="priorityQueue" />
1139 -### priorityQueue(worker, concurrency)
1140 -
1141 -The same as [`queue`](#queue) only tasks are assigned a priority and completed in ascending priority order. There are two differences between `queue` and `priorityQueue` objects:
1142 -
1143 -* `push(task, priority, [callback])` - `priority` should be a number. If an array of
1144 - `tasks` is given, all tasks will be assigned the same priority.
1145 -* The `unshift` method was removed.
1146 -
1147 ----------------------------------------
1148 -
1149 -<a name="cargo" />
1150 -### cargo(worker, [payload])
1151 -
1152 -Creates a `cargo` object with the specified payload. Tasks added to the
1153 -cargo will be processed altogether (up to the `payload` limit). If the
1154 -`worker` is in progress, the task is queued until it becomes available. Once
1155 -the `worker` has completed some tasks, each callback of those tasks is called.
1156 -Check out [this animation](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) for how `cargo` and `queue` work.
1157 -
1158 -While [queue](#queue) passes only one task to one of a group of workers
1159 -at a time, cargo passes an array of tasks to a single worker, repeating
1160 -when the worker is finished.
1161 -
1162 -__Arguments__
1163 -
1164 -* `worker(tasks, callback)` - An asynchronous function for processing an array of
1165 - queued tasks, which must call its `callback(err)` argument when finished, with
1166 - an optional `err` argument.
1167 -* `payload` - An optional `integer` for determining how many tasks should be
1168 - processed per round; if omitted, the default is unlimited.
1169 -
1170 -__Cargo objects__
1171 -
1172 -The `cargo` object returned by this function has the following properties and
1173 -methods:
1174 -
1175 -* `length()` - A function returning the number of items waiting to be processed.
1176 -* `payload` - An `integer` for determining how many tasks should be
1177 - process per round. This property can be changed after a `cargo` is created to
1178 - alter the payload on-the-fly.
1179 -* `push(task, [callback])` - Adds `task` to the `queue`. The callback is called
1180 - once the `worker` has finished processing the task. Instead of a single task, an array of `tasks`
1181 - can be submitted. The respective callback is used for every task in the list.
1182 -* `saturated` - A callback that is called when the `queue.length()` hits the concurrency and further tasks will be queued.
1183 -* `empty` - A callback that is called when the last item from the `queue` is given to a `worker`.
1184 -* `drain` - A callback that is called when the last item from the `queue` has returned from the `worker`.
1185 -
1186 -__Example__
1187 -
1188 -```js
1189 -// create a cargo object with payload 2
1190 -
1191 -var cargo = async.cargo(function (tasks, callback) {
1192 - for(var i=0; i<tasks.length; i++){
1193 - console.log('hello ' + tasks[i].name);
1194 - }
1195 - callback();
1196 -}, 2);
1197 -
1198 -
1199 -// add some items
1200 -
1201 -cargo.push({name: 'foo'}, function (err) {
1202 - console.log('finished processing foo');
1203 -});
1204 -cargo.push({name: 'bar'}, function (err) {
1205 - console.log('finished processing bar');
1206 -});
1207 -cargo.push({name: 'baz'}, function (err) {
1208 - console.log('finished processing baz');
1209 -});
1210 -```
1211 -
1212 ----------------------------------------
1213 -
1214 -<a name="auto" />
1215 -### auto(tasks, [callback])
1216 -
1217 -Determines the best order for running the functions in `tasks`, based on their
1218 -requirements. Each function can optionally depend on other functions being completed
1219 -first, and each function is run as soon as its requirements are satisfied.
1220 -
1221 -If any of the functions pass an error to their callback, it will not
1222 -complete (so any other functions depending on it will not run), and the main
1223 -`callback` is immediately called with the error. Functions also receive an
1224 -object containing the results of functions which have completed so far.
1225 -
1226 -Note, all functions are called with a `results` object as a second argument,
1227 -so it is unsafe to pass functions in the `tasks` object which cannot handle the
1228 -extra argument.
1229 -
1230 -For example, this snippet of code:
1231 -
1232 -```js
1233 -async.auto({
1234 - readData: async.apply(fs.readFile, 'data.txt', 'utf-8')
1235 -}, callback);
1236 -```
1237 -
1238 -will have the effect of calling `readFile` with the results object as the last
1239 -argument, which will fail:
1240 -
1241 -```js
1242 -fs.readFile('data.txt', 'utf-8', cb, {});
1243 -```
1244 -
1245 -Instead, wrap the call to `readFile` in a function which does not forward the
1246 -`results` object:
1247 -
1248 -```js
1249 -async.auto({
1250 - readData: function(cb, results){
1251 - fs.readFile('data.txt', 'utf-8', cb);
1252 - }
1253 -}, callback);
1254 -```
1255 -
1256 -__Arguments__
1257 -
1258 -* `tasks` - An object. Each of its properties is either a function or an array of
1259 - requirements, with the function itself the last item in the array. The object's key
1260 - of a property serves as the name of the task defined by that property,
1261 - i.e. can be used when specifying requirements for other tasks.
1262 - The function receives two arguments: (1) a `callback(err, result)` which must be
1263 - called when finished, passing an `error` (which can be `null`) and the result of
1264 - the function's execution, and (2) a `results` object, containing the results of
1265 - the previously executed functions.
1266 -* `callback(err, results)` - An optional callback which is called when all the
1267 - tasks have been completed. It receives the `err` argument if any `tasks`
1268 - pass an error to their callback. Results are always returned; however, if
1269 - an error occurs, no further `tasks` will be performed, and the results
1270 - object will only contain partial results.
1271 -
1272 -
1273 -__Example__
1274 -
1275 -```js
1276 -async.auto({
1277 - get_data: function(callback){
1278 - console.log('in get_data');
1279 - // async code to get some data
1280 - callback(null, 'data', 'converted to array');
1281 - },
1282 - make_folder: function(callback){
1283 - console.log('in make_folder');
1284 - // async code to create a directory to store a file in
1285 - // this is run at the same time as getting the data
1286 - callback(null, 'folder');
1287 - },
1288 - write_file: ['get_data', 'make_folder', function(callback, results){
1289 - console.log('in write_file', JSON.stringify(results));
1290 - // once there is some data and the directory exists,
1291 - // write the data to a file in the directory
1292 - callback(null, 'filename');
1293 - }],
1294 - email_link: ['write_file', function(callback, results){
1295 - console.log('in email_link', JSON.stringify(results));
1296 - // once the file is written let's email a link to it...
1297 - // results.write_file contains the filename returned by write_file.
1298 - callback(null, {'file':results.write_file, 'email':'user@example.com'});
1299 - }]
1300 -}, function(err, results) {
1301 - console.log('err = ', err);
1302 - console.log('results = ', results);
1303 -});
1304 -```
1305 -
1306 -This is a fairly trivial example, but to do this using the basic parallel and
1307 -series functions would look like this:
1308 -
1309 -```js
1310 -async.parallel([
1311 - function(callback){
1312 - console.log('in get_data');
1313 - // async code to get some data
1314 - callback(null, 'data', 'converted to array');
1315 - },
1316 - function(callback){
1317 - console.log('in make_folder');
1318 - // async code to create a directory to store a file in
1319 - // this is run at the same time as getting the data
1320 - callback(null, 'folder');
1321 - }
1322 -],
1323 -function(err, results){
1324 - async.series([
1325 - function(callback){
1326 - console.log('in write_file', JSON.stringify(results));
1327 - // once there is some data and the directory exists,
1328 - // write the data to a file in the directory
1329 - results.push('filename');
1330 - callback(null);
1331 - },
1332 - function(callback){
1333 - console.log('in email_link', JSON.stringify(results));
1334 - // once the file is written let's email a link to it...
1335 - callback(null, {'file':results.pop(), 'email':'user@example.com'});
1336 - }
1337 - ]);
1338 -});
1339 -```
1340 -
1341 -For a complicated series of `async` tasks, using the [`auto`](#auto) function makes adding
1342 -new tasks much easier (and the code more readable).
1343 -
1344 -
1345 ----------------------------------------
1346 -
1347 -<a name="retry" />
1348 -### retry([times = 5], task, [callback])
1349 -
1350 -Attempts to get a successful response from `task` no more than `times` times before
1351 -returning an error. If the task is successful, the `callback` will be passed the result
1352 -of the successfull task. If all attemps fail, the callback will be passed the error and
1353 -result (if any) of the final attempt.
1354 -
1355 -__Arguments__
1356 -
1357 -* `times` - An integer indicating how many times to attempt the `task` before giving up. Defaults to 5.
1358 -* `task(callback, results)` - A function which receives two arguments: (1) a `callback(err, result)`
1359 - which must be called when finished, passing `err` (which can be `null`) and the `result` of
1360 - the function's execution, and (2) a `results` object, containing the results of
1361 - the previously executed functions (if nested inside another control flow).
1362 -* `callback(err, results)` - An optional callback which is called when the
1363 - task has succeeded, or after the final failed attempt. It receives the `err` and `result` arguments of the last attempt at completing the `task`.
1364 -
1365 -The [`retry`](#retry) function can be used as a stand-alone control flow by passing a
1366 -callback, as shown below:
1367 -
1368 -```js
1369 -async.retry(3, apiMethod, function(err, result) {
1370 - // do something with the result
1371 -});
1372 -```
1373 -
1374 -It can also be embeded within other control flow functions to retry individual methods
1375 -that are not as reliable, like this:
1376 -
1377 -```js
1378 -async.auto({
1379 - users: api.getUsers.bind(api),
1380 - payments: async.retry(3, api.getPayments.bind(api))
1381 -}, function(err, results) {
1382 - // do something with the results
1383 -});
1384 -```
1385 -
1386 -
1387 ----------------------------------------
1388 -
1389 -<a name="iterator" />
1390 -### iterator(tasks)
1391 -
1392 -Creates an iterator function which calls the next function in the `tasks` array,
1393 -returning a continuation to call the next one after that. It's also possible to
1394 -“peek” at the next iterator with `iterator.next()`.
1395 -
1396 -This function is used internally by the `async` module, but can be useful when
1397 -you want to manually control the flow of functions in series.
1398 -
1399 -__Arguments__
1400 -
1401 -* `tasks` - An array of functions to run.
1402 -
1403 -__Example__
1404 -
1405 -```js
1406 -var iterator = async.iterator([
1407 - function(){ sys.p('one'); },
1408 - function(){ sys.p('two'); },
1409 - function(){ sys.p('three'); }
1410 -]);
1411 -
1412 -node> var iterator2 = iterator();
1413 -'one'
1414 -node> var iterator3 = iterator2();
1415 -'two'
1416 -node> iterator3();
1417 -'three'
1418 -node> var nextfn = iterator2.next();
1419 -node> nextfn();
1420 -'three'
1421 -```
1422 -
1423 ----------------------------------------
1424 -
1425 -<a name="apply" />
1426 -### apply(function, arguments..)
1427 -
1428 -Creates a continuation function with some arguments already applied.
1429 -
1430 -Useful as a shorthand when combined with other control flow functions. Any arguments
1431 -passed to the returned function are added to the arguments originally passed
1432 -to apply.
1433 -
1434 -__Arguments__
1435 -
1436 -* `function` - The function you want to eventually apply all arguments to.
1437 -* `arguments...` - Any number of arguments to automatically apply when the
1438 - continuation is called.
1439 -
1440 -__Example__
1441 -
1442 -```js
1443 -// using apply
1444 -
1445 -async.parallel([
1446 - async.apply(fs.writeFile, 'testfile1', 'test1'),
1447 - async.apply(fs.writeFile, 'testfile2', 'test2'),
1448 -]);
1449 -
1450 -
1451 -// the same process without using apply
1452 -
1453 -async.parallel([
1454 - function(callback){
1455 - fs.writeFile('testfile1', 'test1', callback);
1456 - },
1457 - function(callback){
1458 - fs.writeFile('testfile2', 'test2', callback);
1459 - }
1460 -]);
1461 -```
1462 -
1463 -It's possible to pass any number of additional arguments when calling the
1464 -continuation:
1465 -
1466 -```js
1467 -node> var fn = async.apply(sys.puts, 'one');
1468 -node> fn('two', 'three');
1469 -one
1470 -two
1471 -three
1472 -```
1473 -
1474 ----------------------------------------
1475 -
1476 -<a name="nextTick" />
1477 -### nextTick(callback)
1478 -
1479 -Calls `callback` on a later loop around the event loop. In Node.js this just
1480 -calls `process.nextTick`; in the browser it falls back to `setImmediate(callback)`
1481 -if available, otherwise `setTimeout(callback, 0)`, which means other higher priority
1482 -events may precede the execution of `callback`.
1483 -
1484 -This is used internally for browser-compatibility purposes.
1485 -
1486 -__Arguments__
1487 -
1488 -* `callback` - The function to call on a later loop around the event loop.
1489 -
1490 -__Example__
1491 -
1492 -```js
1493 -var call_order = [];
1494 -async.nextTick(function(){
1495 - call_order.push('two');
1496 - // call_order now equals ['one','two']
1497 -});
1498 -call_order.push('one')
1499 -```
1500 -
1501 -<a name="times" />
1502 -### times(n, callback)
1503 -
1504 -Calls the `callback` function `n` times, and accumulates results in the same manner
1505 -you would use with [`map`](#map).
1506 -
1507 -__Arguments__
1508 -
1509 -* `n` - The number of times to run the function.
1510 -* `callback` - The function to call `n` times.
1511 -
1512 -__Example__
1513 -
1514 -```js
1515 -// Pretend this is some complicated async factory
1516 -var createUser = function(id, callback) {
1517 - callback(null, {
1518 - id: 'user' + id
1519 - })
1520 -}
1521 -// generate 5 users
1522 -async.times(5, function(n, next){
1523 - createUser(n, function(err, user) {
1524 - next(err, user)
1525 - })
1526 -}, function(err, users) {
1527 - // we should now have 5 users
1528 -});
1529 -```
1530 -
1531 -<a name="timesSeries" />
1532 -### timesSeries(n, callback)
1533 -
1534 -The same as [`times`](#times), only the iterator is applied to each item in `arr` in
1535 -series. The next `iterator` is only called once the current one has completed.
1536 -The results array will be in the same order as the original.
1537 -
1538 -
1539 -## Utils
1540 -
1541 -<a name="memoize" />
1542 -### memoize(fn, [hasher])
1543 -
1544 -Caches the results of an `async` function. When creating a hash to store function
1545 -results against, the callback is omitted from the hash and an optional hash
1546 -function can be used.
1547 -
1548 -The cache of results is exposed as the `memo` property of the function returned
1549 -by `memoize`.
1550 -
1551 -__Arguments__
1552 -
1553 -* `fn` - The function to proxy and cache results from.
1554 -* `hasher` - Tn optional function for generating a custom hash for storing
1555 - results. It has all the arguments applied to it apart from the callback, and
1556 - must be synchronous.
1557 -
1558 -__Example__
1559 -
1560 -```js
1561 -var slow_fn = function (name, callback) {
1562 - // do something
1563 - callback(null, result);
1564 -};
1565 -var fn = async.memoize(slow_fn);
1566 -
1567 -// fn can now be used as if it were slow_fn
1568 -fn('some name', function () {
1569 - // callback
1570 -});
1571 -```
1572 -
1573 -<a name="unmemoize" />
1574 -### unmemoize(fn)
1575 -
1576 -Undoes a [`memoize`](#memoize)d function, reverting it to the original, unmemoized
1577 -form. Handy for testing.
1578 -
1579 -__Arguments__
1580 -
1581 -* `fn` - the memoized function
1582 -
1583 -<a name="log" />
1584 -### log(function, arguments)
1585 -
1586 -Logs the result of an `async` function to the `console`. Only works in Node.js or
1587 -in browsers that support `console.log` and `console.error` (such as FF and Chrome).
1588 -If multiple arguments are returned from the async function, `console.log` is
1589 -called on each argument in order.
1590 -
1591 -__Arguments__
1592 -
1593 -* `function` - The function you want to eventually apply all arguments to.
1594 -* `arguments...` - Any number of arguments to apply to the function.
1595 -
1596 -__Example__
1597 -
1598 -```js
1599 -var hello = function(name, callback){
1600 - setTimeout(function(){
1601 - callback(null, 'hello ' + name);
1602 - }, 1000);
1603 -};
1604 -```
1605 -```js
1606 -node> async.log(hello, 'world');
1607 -'hello world'
1608 -```
1609 -
1610 ----------------------------------------
1611 -
1612 -<a name="dir" />
1613 -### dir(function, arguments)
1614 -
1615 -Logs the result of an `async` function to the `console` using `console.dir` to
1616 -display the properties of the resulting object. Only works in Node.js or
1617 -in browsers that support `console.dir` and `console.error` (such as FF and Chrome).
1618 -If multiple arguments are returned from the async function, `console.dir` is
1619 -called on each argument in order.
1620 -
1621 -__Arguments__
1622 -
1623 -* `function` - The function you want to eventually apply all arguments to.
1624 -* `arguments...` - Any number of arguments to apply to the function.
1625 -
1626 -__Example__
1627 -
1628 -```js
1629 -var hello = function(name, callback){
1630 - setTimeout(function(){
1631 - callback(null, {hello: name});
1632 - }, 1000);
1633 -};
1634 -```
1635 -```js
1636 -node> async.dir(hello, 'world');
1637 -{hello: 'world'}
1638 -```
1639 -
1640 ----------------------------------------
1641 -
1642 -<a name="noConflict" />
1643 -### noConflict()
1644 -
1645 -Changes the value of `async` back to its original value, returning a reference to the
1646 -`async` object.
1 -{
2 - "name": "async",
3 - "repo": "caolan/async",
4 - "description": "Higher-order functions and common patterns for asynchronous code",
5 - "version": "0.1.23",
6 - "keywords": [],
7 - "dependencies": {},
8 - "development": {},
9 - "main": "lib/async.js",
10 - "scripts": [ "lib/async.js" ]
11 -}
1 -{
2 - "name": "async",
3 - "description": "Higher-order functions and common patterns for asynchronous code",
4 - "main": "./lib/async",
5 - "author": {
6 - "name": "Caolan McMahon"
7 - },
8 - "version": "0.9.0",
9 - "repository": {
10 - "type": "git",
11 - "url": "https://github.com/caolan/async.git"
12 - },
13 - "bugs": {
14 - "url": "https://github.com/caolan/async/issues"
15 - },
16 - "licenses": [
17 - {
18 - "type": "MIT",
19 - "url": "https://github.com/caolan/async/raw/master/LICENSE"
20 - }
21 - ],
22 - "devDependencies": {
23 - "nodeunit": ">0.0.0",
24 - "uglify-js": "1.2.x",
25 - "nodelint": ">0.0.0"
26 - },
27 - "jam": {
28 - "main": "lib/async.js",
29 - "include": [
30 - "lib/async.js",
31 - "README.md",
32 - "LICENSE"
33 - ]
34 - },
35 - "scripts": {
36 - "test": "nodeunit test/test-async.js"
37 - },
38 - "homepage": "https://github.com/caolan/async",
39 - "_id": "async@0.9.0",
40 - "dist": {
41 - "shasum": "ac3613b1da9bed1b47510bb4651b8931e47146c7",
42 - "tarball": "http://registry.npmjs.org/async/-/async-0.9.0.tgz"
43 - },
44 - "_from": "async@",
45 - "_npmVersion": "1.4.3",
46 - "_npmUser": {
47 - "name": "caolan",
48 - "email": "caolan.mcmahon@gmail.com"
49 - },
50 - "maintainers": [
51 - {
52 - "name": "caolan",
53 - "email": "caolan@caolanmcmahon.com"
54 - }
55 - ],
56 - "directories": {},
57 - "_shasum": "ac3613b1da9bed1b47510bb4651b8931e47146c7",
58 - "_resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz",
59 - "readme": "ERROR: No README data found!"
60 -}
1 -before_install:
2 - - sudo apt-get update
3 - - sudo apt-get install imagemagick graphicsmagick
4 -language: node_js
5 -node_js:
6 - - "0.8"
7 - - "0.10"
1 -1.17.0 / 2014-10-28
2 -==================
3 -
4 - * changed: extended compare callback also returns the file names #297 [mastix](https://github.com/mastix)
5 - * changed: pass spawn crash to callback #306 [medikoo](https://github.com/medikoo)
6 - * changed: geometry supports arbitary string as first argument #330 [jdiez17](https://github.com/jdiez17)
7 - * added: support for repage+ option #275 [desigens](https://github.com/desigens)
8 - * added: added the dissolve command #300 [microadm](https://github.com/microadam)
9 - * added: composite method #332 [jdiez17](https://github.com/jdiez17)
10 - * fixed: cannot set tolerance to 0 #302 [rwky](https://github.com/rwky)
11 - * fixed: handle empty buffers #330 [alcidesv](https://github.com/alcidesv)
12 -
13 -1.16.0 / 2014-05-09
14 -==================
15 -
16 - * fixed; dropped "+" when 0 passed as vertical roll amt #267 [dwtkns](https://github.com/dwtkns)
17 - * added; highlight-style support #272 [fdecampredon](https://github.com/fdecampredon)
18 -
19 -1.15.0 / 2014-05-03
20 -===================
21 -
22 - * changed; gm.compare logic to always run the mse comparison as expected #258 [Vokkim](https://github.com/Vokkim)
23 - * added; `tolerance` to gm.compare options object #258 [Vokkim](https://github.com/Vokkim)
24 - * added; option to set ImageMagick application path explicitly #250 (akreitals)
25 - * fixed; gm.compare: support values like 9.51582e-05 #260 [normanrz](https://github.com/normanrz)
26 - * README: add call for maintainers
27 -
28 -1.14.2 / 2013-12-24
29 -===================
30 -
31 -* fixed; background is now a setting #246 (PEM--)
32 -
33 -1.14.1 / 2013-12-09
34 -===================
35 -
36 -* fixed; identify -verbose colon behavior #240 ludow
37 -
38 -1.14.0 / 2013-12-04
39 -===================
40 -
41 -* added; compare method for imagemagick (longlho)
42 -
43 -1.13.3 / 2013-10-22
44 -===================
45 -
46 -* fixed; escape diffOptions.file in compare (dwabyick)
47 -
48 -1.13.2 / 2013-10-18
49 -===================
50 -
51 -* fixed; density is a setting not an operator
52 -
53 -1.13.1 / 2013-09-15
54 -===================
55 -
56 -* added; boolean for % crop
57 -
58 -1.13.0 / 2013-09-07
59 -===================
60 -
61 -* added; morph more than two images (overra)
62 -
63 -1.12.2 / 2013-08-29
64 -===================
65 -
66 -* fixed; fallback to through in node 0.8
67 -
68 -1.12.1 / 2013-08-29 (unpublished)
69 -===================
70 -
71 -* refactor; replace through with stream.PassThrough
72 -
73 -1.12.0 / 2013-08-27
74 -===================
75 -
76 -* added; diff image output file (chenglou)
77 -
78 -1.11.1 / 2013-08-17
79 -===================
80 -
81 -* added; proto.selectFrame(#)
82 -* fixed; getters should not ignore frame selection
83 -
84 -1.11.0 / 2013-07-23
85 -===================
86 -
87 -* added; optional formatting string for gm().identify(format, callback) (tornillo)
88 -* removed; error messages when gm/im binary is not installed
89 -
90 -1.10.0 / 2013-06-27
91 -===================
92 -
93 -* refactor; use native `-auto-orient` for imagemagick
94 -
95 -1.9.2 / 2013-06-12
96 -==================
97 -
98 - * refactor; move `streamToBuffer` to a separate module
99 - * fixed; .stream(format) without a callback
100 -
101 -1.9.1 / 2013-05-07
102 -==================
103 -
104 - * fixed; gm().resize(width) always only resizes width
105 - * fixed; gm('img.gif').format() returns the format of the first frame
106 -
107 -1.9.0 / 2013-04-21
108 -==================
109 -
110 - * added; node v0.10 support
111 - * removed; node < v0.8 support - `Buffer.concat()`
112 - * tests; all tests now run on Travis
113 - * added; gm().stream() returns a stream when no callback is present
114 - * added; gm().toBuffer(callback)
115 - * fixed; gm().size() only returns the size of the first frame of a GIF
116 -
117 -1.8.2 / 2013-03-07
118 -==================
119 -
120 - * include source path in identify data #126 [soupdiver](https://github.com/soupdiver)
121 -
122 -1.8.1 / 2012-12-21
123 -==================
124 -
125 - * Avoid losing already set arguments on identify #105 #113 #109 [JNissi](https://github.com/JNissi)
126 - * tests; add autoOrient + thumb() test
127 - * tests; add test case for #113
128 - * tests; added test for #109
129 - * tests; add resize on buffer test
130 -
131 -1.8.0 / 2012-12-14
132 -==================
133 -
134 - * added; geometry support to scale() #98
135 - * removed; incorrect/broken dissolve() method (never worked)
136 - * fixed; handle child_proc error when using Buffer input #109
137 - * fixed; use of Buffers with identify() #109
138 - * fixed; no longer include -size arg with resize() #98
139 - * fixed; remove -size arg from extent() #103
140 - * fixed; magnify support
141 - * fixed; autoOrient to work with all types of exif orientations [dambalah](https://github.com/dambalah) #108
142 - * tests; npm test runs unit only (now compatible with travis)
143 - * tests; fix magnify test on imagemagick
144 - * tests; added for cmd line args
145 -
146 -1.7.0 / 2012-12-06
147 -==================
148 -
149 - * added; gm.compare support
150 - * added; passing Buffers directly [danmilon](https://github.com/danmilon)
151 -
152 -1.6.1 / 2012-11-13
153 -==================
154 -
155 - * fixed regression; only pass additional params on error #96
156 -
157 -1.6.0 / 2012-11-10
158 -==================
159 -
160 - * changed; rename internal buffer to _buffer #88 [kof](https://github.com/kof)
161 - * changed; optimized identify getters (format, depth, size, color, filesize). #83 please read this for details: https://github.com/aheckmann/gm/commit/8fcf3f8f84a02cc2001da874cbebb89bf7084409
162 - * added; visionmedia/debug support
163 - * added; `gm convert -thumbnail` support. _differs from thumb()._ [danmilon](https://github.com/danmilon)
164 - * fixed; -rotate 0 support #90
165 - * fixed; multi-execution of same gm instance arguments corruption
166 - * fixed; gracefully handle parser errors #94 [eldilibra](https://github.com/eldilibra)
167 -
168 -1.5.1 / 2012-10-02
169 -==================
170 -
171 - * fixed; passing multiple paths to append() #77
172 -
173 -1.5.0 / 2012-09-15
174 -==================
175 -
176 - * fixed; callback scope
177 - * fixed; append() usage #77
178 -
179 -1.4.2 / 2012-08-17
180 -==================
181 -
182 - * fixed; identify parsing for ImageMagick exif data (#58)
183 - * fixed; when in imageMagick mode, complain about missing imageMagick [bcherry](https://github.com/bcherry) (#73)
184 - * added; tests
185 -
186 -1.4.1 / 2012-07-31
187 -==================
188 -
189 - * fixed; scenes() args
190 - * fixed; accept the left-to-right arg of append()
191 - * added; _subCommand
192 -
193 -## v1.4 - 07/28/2012
194 -
195 - * added; adjoin() [Math-]
196 - * added; affine() [Math-]
197 - * added; append() [Math-]
198 - * added; authenticate() [Math-]
199 - * added; average() [Math-]
200 - * added; backdrop() [Math-]
201 - * added; blackThreshold() [Math-]
202 - * added; bluePrimary() [Math-]
203 - * added; border() [Math-]
204 - * added; borderColor() [Math-]
205 - * added; box() [Math-]
206 - * added; channel() [Math-]
207 - * added; clip() [Math-]
208 - * added; coalesce() [Math-]
209 - * added; colorMap() [Math-]
210 - * added; compose() [Math-]
211 - * added; compress() [Math-]
212 - * added; convolve() [Math-]
213 - * added; createDirectories() [Math-]
214 - * added; deconstruct() [Math-]
215 - * added; delay() [Math-]
216 - * added; define() [Math-]
217 - * added; displace() [Math-]
218 - * added; display() [Math-]
219 - * added; dispose() [Math-]
220 - * added; disolve() [Math-]
221 - * added; encoding() [Math-]
222 - * added; endian() [Math-]
223 - * added; file() [Math-]
224 - * added; flatten() [Math-]
225 - * added; foreground() [Math-]
226 - * added; frame() [Math-]
227 - * added; fuzz() [Math-]
228 - * added; gaussian() [Math-]
229 - * added; geometry() [Math-]
230 - * added; greenPrimary() [Math-]
231 - * added; highlightColor() [Math-]
232 - * added; highlightStyle() [Math-]
233 - * added; iconGeometry() [Math-]
234 - * added; intent() [Math-]
235 - * added; lat() [Math-]
236 - * added; level() [Math-]
237 - * added; list() [Math-]
238 - * added; log() [Math-]
239 - * added; map() [Math-]
240 - * added; matte() [Math-]
241 - * added; matteColor() [Math-]
242 - * added; mask() [Math-]
243 - * added; maximumError() [Math-]
244 - * added; mode() [Math-]
245 - * added; monitor() [Math-]
246 - * added; mosaic() [Math-]
247 - * added; motionBlur() [Math-]
248 - * added; name() [Math-]
249 - * added; noop() [Math-]
250 - * added; normalize() [Math-]
251 - * added; opaque() [Math-]
252 - * added; operator() [Math-]
253 - * added; orderedDither() [Math-]
254 - * added; outputDirectory() [Math-]
255 - * added; page() [Math-]
256 - * added; pause() [Math-]
257 - * added; pen() [Math-]
258 - * added; ping() [Math-]
259 - * added; pointSize() [Math-]
260 - * added; preview() [Math-]
261 - * added; process() [Math-]
262 - * added; profile() [Math-]
263 - * added; progress() [Math-]
264 - * added; rawSize() [Math-]
265 - * added; randomThreshold() [Math-]
266 - * added; recolor() [Math-]
267 - * added; redPrimary() [Math-]
268 - * added; remote() [Math-]
269 - * added; render() [Math-]
270 - * added; repage() [Math-]
271 - * added; sample() [Math-]
272 - * added; samplingFactor() [Math-]
273 - * added; scene() [Math-]
274 - * added; scenes() [Math-]
275 - * added; screen() [Math-]
276 - * added; segment() [Math-]
277 - * added; set() [Math-]
278 - * added; shade() [Math-]
279 - * added; shadow() [Math-]
280 - * added; sharedMemory() [Math-]
281 - * added; shave() [Math-]
282 - * added; shear() [Math-]
283 - * added; silent() [Math-]
284 - * added; snaps() [Math-]
285 - * added; stagano() [Math-]
286 - * added; stereo() [Math-]
287 - * added; textFont() [Math-]
288 - * added; texture() [Math-]
289 - * added; threshold() [Math-]
290 - * added; tile() [Math-]
291 - * added; transform() [Math-]
292 - * added; transparent() [Math-]
293 - * added; treeDepth() [Math-]
294 - * added; update() [Math-]
295 - * added; units() [Math-]
296 - * added; unsharp() [Math-]
297 - * added; usePixmap() [Math-]
298 - * added; view() [Math-]
299 - * added; virtualPixel() [Math-]
300 - * added; visual() [Math-]
301 - * added; watermark() [Math-]
302 - * added; wave() [Math-]
303 - * added; whitePoint() [Math-]
304 - * added; whiteThreshold() [Math-]
305 - * added; window() [Math-]
306 - * added; windowGroup() [Math-]
307 -
308 -## v1.3.2 - 06/22/2012
309 -
310 - * added; node >= 0.7/0.8 compat
311 -
312 -## v1.3.1 - 06/06/2012
313 -
314 - * fixed; thumb() alignment and cropping [thomaschaaf]
315 - * added; hint when graphicsmagick is not installed (#62)
316 - * fixed; minify() (#59)
317 -
318 -## v1.3.0 - 04/11/2012
319 -
320 - * added; flatten support [jwarchol]
321 - * added; background support [jwarchol]
322 - * fixed; identify parser error [chriso]
323 -
324 -## v1.2.0 - 03/30/2012
325 -
326 - * added; extent and gravity support [jwarchol]
327 -
328 -## v1.1.0 - 03/15/2012
329 -
330 - * added; filter() support [travisbeck]
331 - * added; density() [travisbeck]
332 - * fixed; permit either width or height in resize [dambalah]
333 - * updated; docs
334 -
335 -## v1.0.5 - 02/15/2012
336 -
337 - * added; strip() support [Math-]
338 - * added; interlace() support [Math-]
339 - * added; setFormat() support [Math-]
340 - * fixed; regexps for image types [Math-]
341 -
342 -## v1.0.4 - 02/09/2012
343 -
344 - * expose utils
345 -
346 -## v1.0.3 - 01/27/2012
347 -
348 - * removed; console.log
349 -
350 -## v1.0.2 - 01/24/2012
351 -
352 - * added; debugging info on parser errors
353 - * fixed; exports.version
354 -
355 -## v1.0.1 - 01/12/2012
356 -
357 - * fixed; use of reserved keyword `super` for node v0.5+
358 -
359 -## v1.0.0 - 01/12/2012
360 -
361 - * added; autoOrient support [kainosnoema] (#21)
362 - * added; orientation support [kainosnoema] (#21)
363 - * fixed; identify parser now properly JSON formats all data output by `gm identify` such as IPTC, GPS, Make, etc (#20)
364 - * added; support for running as imagemagick (#23, #29)
365 - * added; subclassing support; useful for setting default constructor options like one constructor for ImageMagick, the other for GM
366 - * added; more tests
367 - * changed; remove redundant `orientation`, `resolution`, and `filesize` from `this.data` in `indentify()`. Use their uppercase equivalents.
368 -
369 -## v0.6.0 - 12/14/2011
370 -
371 - * added; stream support [kainosnoema] (#22)
372 -
373 -## v0.5.0 - 07/07/2011
374 -
375 - * added; gm#trim() support [lepokle]
376 - * added; gm#inputIs() support
377 - * fixed; 'geometry does not contain image' error: gh-17
378 -
379 -## v0.4.3 - 05/17/2011
380 -
381 - * added; bunch of tests
382 - * fixed; polygon, polyline, bezier drawing bug
383 -
384 -## v0.4.2 - 05/10/2011
385 -
386 - * added; resize options support
387 -
388 -## v0.4.1 - 04/28/2011
389 -
390 - * shell args are now escaped (thanks @visionmedia)
391 - * added; gm.in()
392 - * added; gm.out()
393 - * various refactoring
394 -
395 -## v0.4.0 - 9/21/2010
396 -
397 - * removed deprecated `new` method
398 - * added drawing docs
399 -
400 -## v0.3.2 - 9/06/2010
401 -
402 - * new images are now created using same gm() constructor
403 -
404 -## v0.3.1 - 9/06/2010
405 -
406 - * can now create images from scratch
407 - * add type method
408 -
409 -## v0.3.0 - 8/26/2010
410 -
411 - * add drawing api
412 -
413 -## v0.2.2 - 8/22/2010
414 -
415 - * add quality option to thumb()
416 - * add teropa to contributors
417 - * added support for colorspace()
418 -
419 -## v0.2.1 - 7/31/2010
420 -
421 - * fixed naming conflict. depth() manipulation method renamed bitdepth()
422 - * added better docs
423 -
424 -## v0.2.0 - 7/29/2010
425 -
426 -new methods
427 -
428 - - swirl
429 - - spread
430 - - solarize
431 - - sharpen
432 - - roll
433 - - sepia
434 - - region
435 - - raise
436 - - lower
437 - - paint
438 - - noise
439 - - negative
440 - - morph
441 - - median
442 - - antialias
443 - - limit
444 - - label
445 - - implode
446 - - gamma
447 - - enhance
448 - - equalize
449 - - emboss
450 - - edge
451 - - dither
452 - - monochrome
453 - - despeckle
454 - - depth
455 - - cycle
456 - - contrast
457 - - comment
458 - - colors
459 -
460 -added more default args to several methods
461 -added more examples
462 -
463 -
464 -## v0.1.2 - 7/28/2010
465 -
466 - * refactor project into separate modules
467 -
468 -
469 -## v0.1.1 - 7/27/2010
470 -
471 - * add modulate method
472 - * add colorize method
473 - * add charcoal method
474 - * add chop method
475 - * bug fix in write without a callback
476 -
477 -
478 -## v0.1.0 - 6/27/2010
479 -
480 - * no longer supporting mogrify
481 - * add image data getter methods
482 -
483 - * size
484 - * format
485 - * color
486 - * res
487 - * depth
488 - * filesize
489 - * identify
490 -
491 - * add new convert methods
492 -
493 - * scale
494 - * resample
495 - * rotate
496 - * flip
497 - * flop
498 - * crop
499 - * magnify
500 - * minify
501 - * quality
502 - * blur
503 - * thumb
504 -
505 -
506 -## v0.0.1 - 6/11/2010
507 -Initial release
1 -
2 -test:
3 - @node test/ --integration $(TESTS)
4 -
5 -test-unit:
6 - @node test/ $(TESTS)
7 -
8 -.PHONY: test test-unit
1 -
2 -# gm v1.17.0 [![Build Status](https://travis-ci.org/aheckmann/gm.png?branch=master)](https://travis-ci.org/aheckmann/gm) [![NPM Version](https://img.shields.io/npm/v/gm.svg?style=flat)](https://www.npmjs.org/package/gm)
3 -
4 -GraphicsMagick and ImageMagick for node
5 -
6 -## Getting started
7 -First download and install [GraphicsMagick](http://www.graphicsmagick.org/) or [ImageMagick](http://www.imagemagick.org/). In Mac OS X, you can simply use [Homebrew](http://mxcl.github.io/homebrew/) and do:
8 -
9 - brew install imagemagick
10 - brew install graphicsmagick
11 -
12 -If you want WebP support with ImageMagick, you must add the WebP option:
13 -
14 - brew install imagemagick --with-webp
15 -
16 -then either use npm:
17 -
18 - npm install gm
19 -
20 -or clone the repo:
21 -
22 - git clone git://github.com/aheckmann/gm.git
23 -
24 -
25 -## Use ImageMagick instead of gm
26 -
27 -Just pass the option `{imageMagick: true}` to enable ImageMagick
28 -
29 -```js
30 -var fs = require('fs')
31 - , gm = require('./gm');
32 -
33 -// resize and remove EXIF profile data
34 -gm('/path/to/my/img.jpg')
35 -.options({imageMagick: true})
36 -.resize(240, 240)
37 -...
38 -```
39 -
40 -
41 -## Basic Usage
42 -
43 -```js
44 -var fs = require('fs')
45 - , gm = require('./gm');
46 -
47 -// resize and remove EXIF profile data
48 -gm('/path/to/my/img.jpg')
49 -.resize(240, 240)
50 -.noProfile()
51 -.write('/path/to/resize.png', function (err) {
52 - if (!err) console.log('done');
53 -});
54 -
55 -// obtain the size of an image
56 -gm('/path/to/my/img.jpg')
57 -.size(function (err, size) {
58 - if (!err)
59 - console.log(size.width > size.height ? 'wider' : 'taller than you');
60 -});
61 -
62 -// output all available image properties
63 -gm('/path/to/img.png')
64 -.identify(function (err, data) {
65 - if (!err) console.log(data)
66 -});
67 -
68 -// pull out the first frame of an animated gif and save as png
69 -gm('/path/to/animated.gif[0]')
70 -.write('/path/to/firstframe.png', function (err) {
71 - if (err) console.log('aaw, shucks');
72 -});
73 -
74 -// auto-orient an image
75 -gm('/path/to/img.jpg')
76 -.autoOrient()
77 -.write('/path/to/oriented.jpg', function (err) {
78 - if (err) ...
79 -})
80 -
81 -// crazytown
82 -gm('/path/to/my/img.jpg')
83 -.flip()
84 -.magnify()
85 -.rotate('green', 45)
86 -.blur(7, 3)
87 -.crop(300, 300, 150, 130)
88 -.edge(3)
89 -.write('/path/to/crazy.jpg', function (err) {
90 - if (!err) console.log('crazytown has arrived');
91 -})
92 -
93 -// annotate an image
94 -gm('/path/to/my/img.jpg')
95 -.stroke("#ffffff")
96 -.drawCircle(10, 10, 20, 10)
97 -.font("Helvetica.ttf", 12)
98 -.drawText(30, 20, "GMagick!")
99 -.write("/path/to/drawing.png", function (err) {
100 - if (!err) console.log('done');
101 -});
102 -
103 -// creating an image
104 -gm(200, 400, "#ddff99f3")
105 -.drawText(10, 50, "from scratch")
106 -.write("/path/to/brandNewImg.jpg", function (err) {
107 - // ...
108 -});
109 -```
110 -
111 -## Streams
112 -
113 -```js
114 -// passing a stream
115 -var readStream = fs.createReadStream('/path/to/my/img.jpg');
116 -gm(readStream, 'img.jpg')
117 -.write('/path/to/reformat.png', function (err) {
118 - if (!err) console.log('done');
119 -});
120 -
121 -// can also stream output to a ReadableStream
122 -// (can be piped to a local file or remote server)
123 -gm('/path/to/my/img.jpg')
124 -.resize('200', '200')
125 -.stream(function (err, stdout, stderr) {
126 - var writeStream = fs.createWriteStream('/path/to/my/resized.jpg');
127 - stdout.pipe(writeStream);
128 -});
129 -
130 -// without a callback, .stream() returns a stream
131 -// this is just a convenience wrapper for above.
132 -var writeStream = fs.createWriteStream('/path/to/my/resized.jpg');
133 -gm('/path/to/my/img.jpg')
134 -.resize('200', '200')
135 -.stream()
136 -.pipe(writeStream);
137 -
138 -// pass a format or filename to stream() and
139 -// gm will provide image data in that format
140 -gm('/path/to/my/img.jpg')
141 -.stream('png', function (err, stdout, stderr) {
142 - var writeStream = fs.createWriteStream('/path/to/my/reformated.png');
143 - stdout.pipe(writeStream);
144 -});
145 -
146 -// or without the callback
147 -var writeStream = fs.createWriteStream('/path/to/my/reformated.png');
148 -gm('/path/to/my/img.jpg')
149 -.stream('png')
150 -.pipe(writeStream);
151 -
152 -// combine the two for true streaming image processing
153 -var readStream = fs.createReadStream('/path/to/my/img.jpg');
154 -gm(readStream, 'img.jpg')
155 -.resize('200', '200')
156 -.stream(function (err, stdout, stderr) {
157 - var writeStream = fs.createWriteStream('/path/to/my/resized.jpg');
158 - stdout.pipe(writeStream);
159 -});
160 -
161 -// GOTCHA:
162 -// when working with input streams and any 'identify'
163 -// operation (size, format, etc), you must pass "{bufferStream: true}" if
164 -// you also need to convert (write() or stream()) the image afterwards
165 -// NOTE: this buffers the readStream in memory!
166 -var readStream = fs.createReadStream('/path/to/my/img.jpg');
167 -gm(readStream, 'img.jpg')
168 -.size({bufferStream: true}, function(err, size) {
169 - this.resize(size.width / 2, size.height / 2)
170 - this.write('/path/to/resized.jpg', function (err) {
171 - if (!err) console.log('done');
172 - });
173 -});
174 -
175 -```
176 -
177 -## Buffers
178 -
179 -```js
180 -// A buffer can be passed instead of a filepath as well
181 -var buf = require('fs').readFileSync('/path/to/image.jpg');
182 -
183 -gm(buf, 'image.jpg')
184 -.noise('laplacian')
185 -.write('/path/to/out.jpg', function (err) {
186 - if (err) return handle(err);
187 - console.log('Created an image from a Buffer!');
188 -});
189 -
190 -/*
191 -A buffer can also be returned instead of a stream
192 -The first argument to toBuffer is optional, it specifies the image format
193 -*/
194 -gm('img.jpg')
195 -.resize(100, 100)
196 -.toBuffer('PNG',function (err, buffer) {
197 - if (err) return handle(err);
198 - console.log('done!');
199 -})
200 -```
201 -
202 -## Custom Arguments
203 -
204 -If `gm` does not supply you with a method you need or does not work as you'd like, you can simply use `gm().in()` or `gm().out()` to set your own arguments.
205 -
206 -- `gm().command()` - Custom command such as `identify` or `convert`
207 -- `gm().in()` - Custom input arguments
208 -- `gm().out()` - Custom output arguments
209 -
210 -The command will be formatted in the following order:
211 -
212 -1. `command` - ie `convert`
213 -2. `in` - the input arguments
214 -3. `source` - stdin or an image file
215 -4. `out` - the output arguments
216 -5. `output` - stdout or the image file to write to
217 -
218 -For example, suppose you want the following command:
219 -
220 -```bash
221 -gm "convert" "label:Offline" "PNG:-"
222 -```
223 -
224 -However, using `gm().label()` may not work as intended for you:
225 -
226 -```js
227 -gm()
228 -.label('Offline')
229 -.stream();
230 -```
231 -
232 -would yield:
233 -
234 -```bash
235 -gm "convert" "-label" "\"Offline\"" "PNG:-"
236 -```
237 -
238 -Instead, you can use `gm().out()`:
239 -
240 -```js
241 -gm()
242 -.out('label:Offline')
243 -.stream();
244 -```
245 -
246 -which correctly yields:
247 -
248 -```bash
249 -gm "convert" "label:Offline" "PNG:-"
250 -```
251 -
252 -### Custom Identify Format String
253 -
254 -When identifying an image, you may want to use a custom formatting string instead of using `-verbose`, which is quite slow.
255 -You can use your own [formatting string](http://www.imagemagick.org/script/escape.php) when using `gm().identify(format, callback)`.
256 -For example,
257 -
258 -```js
259 -gm('img.png').format(function (err, format) {
260 -
261 -})
262 -
263 -// is equivalent to
264 -
265 -gm('img.png').identify('%m', function (err, format) {
266 -
267 -})
268 -```
269 -
270 -since `%m` is the format option for getting the image file format.
271 -
272 -## Platform differences
273 -
274 -Please document and refer to any [platform or ImageMagick/GraphicsMagick issues/differences here](https://github.com/aheckmann/gm/wiki/GraphicsMagick-and-ImageMagick-versions).
275 -
276 -## Examples:
277 -
278 - Check out the [examples](http://github.com/aheckmann/gm/tree/master/examples/) directory to play around.
279 - Also take a look at the [extending gm](http://wiki.github.com/aheckmann/gm/extending-gm)
280 - page to see how to customize gm to your own needs.
281 -
282 -## Constructor:
283 -
284 - There are a few ways you can use the `gm` image constructor.
285 -
286 - - 1) `gm(path)` When you pass a string as the first argument it is interpreted as the path to an image you intend to manipulate.
287 - - 2) `gm(stream || buffer, [filename])` You may also pass a ReadableStream or Buffer as the first argument, with an optional file name for format inference.
288 - - 3) `gm(width, height, [color])` When you pass two integer arguments, gm will create a new image on the fly with the provided dimensions and an optional background color. And you can still chain just like you do with pre-existing images too. See [here](http://github.com/aheckmann/gm/blob/master/examples/new.js) for an example.
289 -
290 -## Methods
291 -
292 - - getters
293 - - [size](http://aheckmann.github.com/gm/docs.html#getters) - returns the size (WxH) of the image
294 - - [orientation](http://aheckmann.github.com/gm/docs.html#orientation) - returns the EXIF orientation of the image
295 - - [format](http://aheckmann.github.com/gm/docs.html#getters) - returns the image format (gif, jpeg, png, etc)
296 - - [depth](http://aheckmann.github.com/gm/docs.html#getters) - returns the image color depth
297 - - [color](http://aheckmann.github.com/gm/docs.html#getters) - returns the number of colors
298 - - [res](http://aheckmann.github.com/gm/docs.html#getters) - returns the image resolution
299 - - [filesize](http://aheckmann.github.com/gm/docs.html#getters) - returns image filesize
300 - - [identify](http://aheckmann.github.com/gm/docs.html#getters) - returns all image data available. Takes an optional format string.
301 -
302 - - manipulation
303 - - [adjoin](http://aheckmann.github.com/gm/docs.html#adjoin)
304 - - [affine](http://aheckmann.github.com/gm/docs.html#affine)
305 - - [antialias](http://aheckmann.github.com/gm/docs.html#antialias)
306 - - [append](http://aheckmann.github.com/gm/docs.html#append)
307 - - [authenticate](http://aheckmann.github.com/gm/docs.html#authenticate)
308 - - [autoOrient](http://aheckmann.github.com/gm/docs.html#autoOrient)
309 - - [average](http://aheckmann.github.com/gm/docs.html#average)
310 - - [backdrop](http://aheckmann.github.com/gm/docs.html#backdrop)
311 - - [bitdepth](http://aheckmann.github.com/gm/docs.html#bitdepth)
312 - - [blackThreshold](http://aheckmann.github.com/gm/docs.html#blackThreshold)
313 - - [bluePrimary](http://aheckmann.github.com/gm/docs.html#bluePrimary)
314 - - [blur](http://aheckmann.github.com/gm/docs.html#blur)
315 - - [border](http://aheckmann.github.com/gm/docs.html#border)
316 - - [borderColor](http://aheckmann.github.com/gm/docs.html#borderColor)
317 - - [box](http://aheckmann.github.com/gm/docs.html#box)
318 - - [channel](http://aheckmann.github.com/gm/docs.html#channel)
319 - - [charcoal](http://aheckmann.github.com/gm/docs.html#charcoal)
320 - - [chop](http://aheckmann.github.com/gm/docs.html#chop)
321 - - [clip](http://aheckmann.github.com/gm/docs.html#clip)
322 - - [coalesce](http://aheckmann.github.com/gm/docs.html#coalesce)
323 - - [colors](http://aheckmann.github.com/gm/docs.html#colors)
324 - - [colorize](http://aheckmann.github.com/gm/docs.html#colorize)
325 - - [colorMap](http://aheckmann.github.com/gm/docs.html#colorMap)
326 - - [colorspace](http://aheckmann.github.com/gm/docs.html#colorspace)
327 - - [comment](http://aheckmann.github.com/gm/docs.html#comment)
328 - - [compose](http://aheckmann.github.com/gm/docs.html#compose)
329 - - [compress](http://aheckmann.github.com/gm/docs.html#compress)
330 - - [contrast](http://aheckmann.github.com/gm/docs.html#contrast)
331 - - [convolve](http://aheckmann.github.com/gm/docs.html#convolve)
332 - - [createDirectories](http://aheckmann.github.com/gm/docs.html#createDirectories)
333 - - [crop](http://aheckmann.github.com/gm/docs.html#crop)
334 - - [cycle](http://aheckmann.github.com/gm/docs.html#cycle)
335 - - [deconstruct](http://aheckmann.github.com/gm/docs.html#deconstruct)
336 - - [delay](http://aheckmann.github.com/gm/docs.html#delay)
337 - - [define](http://aheckmann.github.com/gm/docs.html#define)
338 - - [density](http://aheckmann.github.com/gm/docs.html#density)
339 - - [despeckle](http://aheckmann.github.com/gm/docs.html#despeckle)
340 - - [dither](http://aheckmann.github.com/gm/docs.html#dither)
341 - - [displace](http://aheckmann.github.com/gm/docs.html#dither)
342 - - [display](http://aheckmann.github.com/gm/docs.html#display)
343 - - [dispose](http://aheckmann.github.com/gm/docs.html#dispose)
344 - - [dissolve](http://aheckmann.github.com/gm/docs.html#dissolve)
345 - - [edge](http://aheckmann.github.com/gm/docs.html#edge)
346 - - [emboss](http://aheckmann.github.com/gm/docs.html#emboss)
347 - - [encoding](http://aheckmann.github.com/gm/docs.html#encoding)
348 - - [enhance](http://aheckmann.github.com/gm/docs.html#enhance)
349 - - [endian](http://aheckmann.github.com/gm/docs.html#endian)
350 - - [equalize](http://aheckmann.github.com/gm/docs.html#equalize)
351 - - [extent](http://aheckmann.github.com/gm/docs.html#extent)
352 - - [file](http://aheckmann.github.com/gm/docs.html#file)
353 - - [filter](http://aheckmann.github.com/gm/docs.html#filter)
354 - - [flatten](http://aheckmann.github.com/gm/docs.html#flatten)
355 - - [flip](http://aheckmann.github.com/gm/docs.html#flip)
356 - - [flop](http://aheckmann.github.com/gm/docs.html#flop)
357 - - [foreground](http://aheckmann.github.com/gm/docs.html#foreground)
358 - - [frame](http://aheckmann.github.com/gm/docs.html#frame)
359 - - [fuzz](http://aheckmann.github.com/gm/docs.html#fuzz)
360 - - [gamma](http://aheckmann.github.com/gm/docs.html#gamma)
361 - - [gaussian](http://aheckmann.github.com/gm/docs.html#gaussian)
362 - - [geometry](http://aheckmann.github.com/gm/docs.html#geometry)
363 - - [gravity](http://aheckmann.github.com/gm/docs.html#gravity)
364 - - [greenPrimary](http://aheckmann.github.com/gm/docs.html#greenPrimary)
365 - - [highlightColor](http://aheckmann.github.com/gm/docs.html#highlightColor)
366 - - [highlightStyle](http://aheckmann.github.com/gm/docs.html#highlightStyle)
367 - - [iconGeometry](http://aheckmann.github.com/gm/docs.html#iconGeometry)
368 - - [implode](http://aheckmann.github.com/gm/docs.html#implode)
369 - - [intent](http://aheckmann.github.com/gm/docs.html#intent)
370 - - [interlace](http://aheckmann.github.com/gm/docs.html#interlace)
371 - - [label](http://aheckmann.github.com/gm/docs.html#label)
372 - - [lat](http://aheckmann.github.com/gm/docs.html#lat)
373 - - [level](http://aheckmann.github.com/gm/docs.html#level)
374 - - [list](http://aheckmann.github.com/gm/docs.html#list)
375 - - [limit](http://aheckmann.github.com/gm/docs.html#limit)
376 - - [log](http://aheckmann.github.com/gm/docs.html#log)
377 - - [loop](http://aheckmann.github.com/gm/docs.html#loop)
378 - - [lower](http://aheckmann.github.com/gm/docs.html#lower)
379 - - [magnify](http://aheckmann.github.com/gm/docs.html#magnify)
380 - - [map](http://aheckmann.github.com/gm/docs.html#map)
381 - - [matte](http://aheckmann.github.com/gm/docs.html#matte)
382 - - [matteColor](http://aheckmann.github.com/gm/docs.html#matteColor)
383 - - [mask](http://aheckmann.github.com/gm/docs.html#mask)
384 - - [maximumError](http://aheckmann.github.com/gm/docs.html#maximumError)
385 - - [median](http://aheckmann.github.com/gm/docs.html#median)
386 - - [minify](http://aheckmann.github.com/gm/docs.html#minify)
387 - - [mode](http://aheckmann.github.com/gm/docs.html#mode)
388 - - [modulate](http://aheckmann.github.com/gm/docs.html#modulate)
389 - - [monitor](http://aheckmann.github.com/gm/docs.html#monitor)
390 - - [monochrome](http://aheckmann.github.com/gm/docs.html#monochrome)
391 - - [morph](http://aheckmann.github.com/gm/docs.html#morph)
392 - - [mosaic](http://aheckmann.github.com/gm/docs.html#mosaic)
393 - - [motionBlur](http://aheckmann.github.com/gm/docs.html#motionBlur)
394 - - [name](http://aheckmann.github.com/gm/docs.html#name)
395 - - [negative](http://aheckmann.github.com/gm/docs.html#negative)
396 - - [noise](http://aheckmann.github.com/gm/docs.html#noise)
397 - - [noop](http://aheckmann.github.com/gm/docs.html#noop)
398 - - [normalize](http://aheckmann.github.com/gm/docs.html#normalize)
399 - - [noProfile](http://aheckmann.github.com/gm/docs.html#profile)
400 - - [opaque](http://aheckmann.github.com/gm/docs.html#opaque)
401 - - [operator](http://aheckmann.github.com/gm/docs.html#operator)
402 - - [orderedDither](http://aheckmann.github.com/gm/docs.html#orderedDither)
403 - - [outputDirectory](http://aheckmann.github.com/gm/docs.html#outputDirectory)
404 - - [paint](http://aheckmann.github.com/gm/docs.html#paint)
405 - - [page](http://aheckmann.github.com/gm/docs.html#page)
406 - - [pause](http://aheckmann.github.com/gm/docs.html#pause)
407 - - [pen](http://aheckmann.github.com/gm/docs.html#pen)
408 - - [ping](http://aheckmann.github.com/gm/docs.html#ping)
409 - - [pointSize](http://aheckmann.github.com/gm/docs.html#pointSize)
410 - - [preview](http://aheckmann.github.com/gm/docs.html#preview)
411 - - [process](http://aheckmann.github.com/gm/docs.html#process)
412 - - [profile](http://aheckmann.github.com/gm/docs.html#profile)
413 - - [progress](http://aheckmann.github.com/gm/docs.html#progress)
414 - - [quality](http://aheckmann.github.com/gm/docs.html#quality)
415 - - [raise](http://aheckmann.github.com/gm/docs.html#raise)
416 - - [rawSize](http://aheckmann.github.com/gm/docs.html#rawSize)
417 - - [randomThreshold](http://aheckmann.github.com/gm/docs.html#randomThreshold)
418 - - [recolor](http://aheckmann.github.com/gm/docs.html#recolor)
419 - - [redPrimary](http://aheckmann.github.com/gm/docs.html#redPrimary)
420 - - [region](http://aheckmann.github.com/gm/docs.html#region)
421 - - [remote](http://aheckmann.github.com/gm/docs.html#remote)
422 - - [render](http://aheckmann.github.com/gm/docs.html#render)
423 - - [repage](http://aheckmann.github.com/gm/docs.html#repage)
424 - - [resample](http://aheckmann.github.com/gm/docs.html#resample)
425 - - [resize](http://aheckmann.github.com/gm/docs.html#resize)
426 - - [roll](http://aheckmann.github.com/gm/docs.html#roll)
427 - - [rotate](http://aheckmann.github.com/gm/docs.html#rotate)
428 - - [sample](http://aheckmann.github.com/gm/docs.html#sample)
429 - - [samplingFactor](http://aheckmann.github.com/gm/docs.html#samplingFactor)
430 - - [scale](http://aheckmann.github.com/gm/docs.html#scale)
431 - - [scene](http://aheckmann.github.com/gm/docs.html#scene)
432 - - [scenes](http://aheckmann.github.com/gm/docs.html#scenes)
433 - - [screen](http://aheckmann.github.com/gm/docs.html#screen)
434 - - [segment](http://aheckmann.github.com/gm/docs.html#segment)
435 - - [sepia](http://aheckmann.github.com/gm/docs.html#sepia)
436 - - [set](http://aheckmann.github.com/gm/docs.html#set)
437 - - [setFormat](http://aheckmann.github.com/gm/docs.html#setformat)
438 - - [shade](http://aheckmann.github.com/gm/docs.html#shade)
439 - - [shadow](http://aheckmann.github.com/gm/docs.html#shadow)
440 - - [sharedMemory](http://aheckmann.github.com/gm/docs.html#sharedMemory)
441 - - [sharpen](http://aheckmann.github.com/gm/docs.html#sharpen)
442 - - [shave](http://aheckmann.github.com/gm/docs.html#shave)
443 - - [shear](http://aheckmann.github.com/gm/docs.html#shear)
444 - - [silent](http://aheckmann.github.com/gm/docs.html#silent)
445 - - [solarize](http://aheckmann.github.com/gm/docs.html#solarize)
446 - - [snaps](http://aheckmann.github.com/gm/docs.html#snaps)
447 - - [stegano](http://aheckmann.github.com/gm/docs.html#stegano)
448 - - [stereo](http://aheckmann.github.com/gm/docs.html#stereo)
449 - - [strip](http://aheckmann.github.com/gm/docs.html#strip) _imagemagick only_
450 - - [spread](http://aheckmann.github.com/gm/docs.html#spread)
451 - - [swirl](http://aheckmann.github.com/gm/docs.html#swirl)
452 - - [textFont](http://aheckmann.github.com/gm/docs.html#textFont)
453 - - [texture](http://aheckmann.github.com/gm/docs.html#texture)
454 - - [threshold](http://aheckmann.github.com/gm/docs.html#threshold)
455 - - [thumb](http://aheckmann.github.com/gm/docs.html#thumb)
456 - - [tile](http://aheckmann.github.com/gm/docs.html#tile)
457 - - [transform](http://aheckmann.github.com/gm/docs.html#transform)
458 - - [transparent](http://aheckmann.github.com/gm/docs.html#transparent)
459 - - [treeDepth](http://aheckmann.github.com/gm/docs.html#treeDepth)
460 - - [trim](http://aheckmann.github.com/gm/docs.html#trim)
461 - - [type](http://aheckmann.github.com/gm/docs.html#type)
462 - - [update](http://aheckmann.github.com/gm/docs.html#update)
463 - - [units](http://aheckmann.github.com/gm/docs.html#units)
464 - - [unsharp](http://aheckmann.github.com/gm/docs.html#unsharp)
465 - - [usePixmap](http://aheckmann.github.com/gm/docs.html#usePixmap)
466 - - [view](http://aheckmann.github.com/gm/docs.html#view)
467 - - [virtualPixel](http://aheckmann.github.com/gm/docs.html#virtualPixel)
468 - - [visual](http://aheckmann.github.com/gm/docs.html#visual)
469 - - [watermark](http://aheckmann.github.com/gm/docs.html#watermark)
470 - - [wave](http://aheckmann.github.com/gm/docs.html#wave)
471 - - [whitePoint](http://aheckmann.github.com/gm/docs.html#whitePoint)
472 - - [whiteThreshold](http://aheckmann.github.com/gm/docs.html#whiteThreshold)
473 - - [window](http://aheckmann.github.com/gm/docs.html#window)
474 - - [windowGroup](http://aheckmann.github.com/gm/docs.html#windowGroup)
475 -
476 - - drawing primitives
477 - - [draw](http://aheckmann.github.com/gm/docs.html#draw)
478 - - [drawArc](http://aheckmann.github.com/gm/docs.html#drawArc)
479 - - [drawBezier](http://aheckmann.github.com/gm/docs.html#drawBezier)
480 - - [drawCircle](http://aheckmann.github.com/gm/docs.html#drawCircle)
481 - - [drawEllipse](http://aheckmann.github.com/gm/docs.html#drawEllipse)
482 - - [drawLine](http://aheckmann.github.com/gm/docs.html#drawLine)
483 - - [drawPoint](http://aheckmann.github.com/gm/docs.html#drawPoint)
484 - - [drawPolygon](http://aheckmann.github.com/gm/docs.html#drawPolygon)
485 - - [drawPolyline](http://aheckmann.github.com/gm/docs.html#drawPolyline)
486 - - [drawRectangle](http://aheckmann.github.com/gm/docs.html#drawRectangle)
487 - - [drawText](http://aheckmann.github.com/gm/docs.html#drawText)
488 - - [fill](http://aheckmann.github.com/gm/docs.html#fill)
489 - - [font](http://aheckmann.github.com/gm/docs.html#font)
490 - - [fontSize](http://aheckmann.github.com/gm/docs.html#fontSize)
491 - - [stroke](http://aheckmann.github.com/gm/docs.html#stroke)
492 - - [strokeWidth](http://aheckmann.github.com/gm/docs.html#strokeWidth)
493 - - [setDraw](http://aheckmann.github.com/gm/docs.html#setDraw)
494 -
495 - - image output
496 - - **write** - writes the processed image data to the specified filename
497 - - **stream** - provides a `ReadableStream` with the processed image data
498 - - **toBuffer** - returns the image as a `Buffer` instead of a stream
499 -
500 -##compare
501 -
502 -Graphicsmagicks `compare` command is exposed through `gm.compare()`. This allows us to determine if two images can be considered "equal".
503 -
504 -Currently `gm.compare` only accepts file paths.
505 -
506 - gm.compare(path1, path2 [, options], callback)
507 -
508 -```js
509 -gm.compare('/path/to/image1.jpg', '/path/to/another.png', function (err, isEqual, equality, raw, path1, path2) {
510 - if (err) return handle(err);
511 -
512 - // if the images were considered equal, `isEqual` will be true, otherwise, false.
513 - console.log('The images were equal: %s', isEqual);
514 -
515 - // to see the total equality returned by graphicsmagick we can inspect the `equality` argument.
516 - console.log('Actual equality: %d', equality);
517 -
518 - // inspect the raw output
519 - console.log(raw);
520 -
521 - // print file paths
522 - console.log(path1, path2);
523 -})
524 -```
525 -
526 -You may wish to pass a custom tolerance threshold to increase or decrease the default level of `0.4`.
527 -
528 -
529 -```js
530 -gm.compare('/path/to/image1.jpg', '/path/to/another.png', 1.2, function (err, isEqual) {
531 - ...
532 -})
533 -```
534 -
535 -To output a diff image, pass a configuration object to define the diff options and tolerance.
536 -
537 -
538 -```js
539 -var options = {
540 - file: '/path/to/diff.png',
541 - highlightColor: 'yellow',
542 - tolerance: 0.02
543 -}
544 -gm.compare('/path/to/image1.jpg', '/path/to/another.png', options, function (err, isEqual, equality, raw) {
545 - ...
546 -})
547 -```
548 -
549 -##composite
550 -
551 -GraphicsMagick supports compositing one image on top of another. This is exposed through `gm.composite()`. Its first argument is an image path with the changes to the base image, and an optional mask image.
552 -
553 -Currently, `gm.composite()` only accepts file paths.
554 -
555 - gm.composite(other [, mask])
556 -
557 -```js
558 -gm('/path/to/image.jpg')
559 -.composite('/path/to/second_image.jpg')
560 -.geometry('+100+150')
561 -.write('/path/to/composite.png', function(err) {
562 - if(!err) console.log("Written composite image.");
563 -});
564 -```
565 -
566 -## Contributors
567 -[https://github.com/aheckmann/gm/contributors](https://github.com/aheckmann/gm/contributors)
568 -
569 -## Inspiration
570 -http://github.com/quiiver/magickal-node
571 -
572 -## Plugins
573 -[https://github.com/aheckmann/gm/wiki](https://github.com/aheckmann/gm/wiki)
574 -
575 -## License
576 -
577 -(The MIT License)
578 -
579 -Copyright (c) 2010 [Aaron Heckmann](aaron.heckmann+github@gmail.com)
580 -
581 -Permission is hereby granted, free of charge, to any person obtaining
582 -a copy of this software and associated documentation files (the
583 -'Software'), to deal in the Software without restriction, including
584 -without limitation the rights to use, copy, modify, merge, publish,
585 -distribute, sublicense, and/or sell copies of the Software, and to
586 -permit persons to whom the Software is furnished to do so, subject to
587 -the following conditions:
588 -
589 -The above copyright notice and this permission notice shall be
590 -included in all copies or substantial portions of the Software.
591 -
592 -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
593 -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
594 -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
595 -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
596 -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
597 -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
598 -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 -
2 -/**
3 - * Module dependencies.
4 - */
5 -
6 -var Stream = require('stream').Stream;
7 -var EventEmitter = require('events').EventEmitter;
8 -var util = require('util');
9 -
10 -util.inherits(gm, EventEmitter);
11 -
12 -/**
13 - * Constructor.
14 - *
15 - * @param {String|Number} path - path to img source or ReadableStream or width of img to create
16 - * @param {Number} [height] - optional filename of ReadableStream or height of img to create
17 - * @param {String} [color] - optional hex background color of created img
18 - */
19 -
20 -function gm (source, height, color) {
21 - var width;
22 -
23 - if (!(this instanceof gm)) {
24 - return new gm(source, height, color);
25 - }
26 -
27 - EventEmitter.call(this);
28 -
29 - this._options = {};
30 - this.options(this.__proto__._options);
31 -
32 - this.data = {};
33 - this._in = [];
34 - this._out = [];
35 - this._outputFormat = null;
36 - this._subCommand = 'convert';
37 -
38 - if (source instanceof Stream) {
39 - this.sourceStream = source;
40 - source = height || 'unknown.jpg';
41 - } else if (Buffer.isBuffer(source)) {
42 - this.sourceBuffer = source;
43 - source = height || 'unknown.jpg';
44 - } else if (height) {
45 - // new images
46 - width = source;
47 - source = "";
48 -
49 - this.in("-size", width + "x" + height);
50 -
51 - if (color) {
52 - this.in("xc:"+ color);
53 - }
54 - }
55 -
56 - if (typeof source === "string") {
57 - // then source is a path
58 -
59 - // parse out gif frame brackets from filename
60 - // since stream doesn't use source path
61 - // eg. "filename.gif[0]"
62 - var frames = source.match(/(\[.+\])$/);
63 - if (frames) {
64 - this.sourceFrames = source.substr(frames.index, frames[0].length);
65 - source = source.substr(0, frames.index);
66 - }
67 - }
68 -
69 - this.source = source;
70 -
71 - this.addSrcFormatter(function (src) {
72 - // must be first source formatter
73 -
74 - var inputFromStdin = this.sourceStream || this.sourceBuffer;
75 - var ret = inputFromStdin ? '-' : this.source;
76 -
77 - if (ret && this.sourceFrames) ret += this.sourceFrames;
78 -
79 - src.length = 0;
80 - src[0] = ret;
81 - });
82 -}
83 -
84 -/**
85 - * Subclasses the gm constructor with custom options.
86 - *
87 - * @param {options} options
88 - * @return {gm} the subclasses gm constructor
89 - */
90 -
91 -var parent = gm;
92 -gm.subClass = function subClass (options) {
93 - function gm (source, height, color) {
94 - if (!(this instanceof parent)) {
95 - return new gm(source, height, color);
96 - }
97 -
98 - parent.call(this, source, height, color);
99 - }
100 -
101 - gm.prototype.__proto__ = parent.prototype;
102 - gm.prototype._options = {};
103 - gm.prototype.options(options);
104 -
105 - return gm;
106 -}
107 -
108 -/**
109 - * Augment the prototype.
110 - */
111 -
112 -require("./lib/options")(gm.prototype);
113 -require("./lib/getters")(gm);
114 -require("./lib/args")(gm.prototype);
115 -require("./lib/drawing")(gm.prototype);
116 -require("./lib/convenience")(gm.prototype);
117 -require("./lib/command")(gm.prototype);
118 -require("./lib/compare")(gm.prototype);
119 -require("./lib/composite")(gm.prototype);
120 -
121 -/**
122 - * Expose.
123 - */
124 -
125 -module.exports = exports = gm;
126 -module.exports.utils = require('./lib/utils');
127 -module.exports.compare = require('./lib/compare')();
128 -module.exports.version = JSON.parse(
129 - require('fs').readFileSync(__dirname + '/package.json', 'utf8')
130 -).version;
131 -
1 -# Compiled source #
2 -###################
3 -*.com
4 -*.class
5 -*.dll
6 -*.exe
7 -*.o
8 -*.so
9 -
10 -# Packages #
11 -############
12 -# it's better to unpack these files and commit the raw source
13 -# git has its own built in compression methods
14 -*.7z
15 -*.dmg
16 -*.gz
17 -*.iso
18 -*.jar
19 -*.rar
20 -*.tar
21 -*.zip
22 -
23 -# Logs and databases #
24 -######################
25 -*.log
26 -*.sql
27 -*.sqlite
28 -
29 -# OS generated files #
30 -######################
31 -.DS_Store*
32 -ehthumbs.db
33 -Icon?
34 -Thumbs.db
35 -
36 -# Node.js #
37 -###########
38 -lib-cov
39 -*.seed
40 -*.log
41 -*.csv
42 -*.dat
43 -*.out
44 -*.pid
45 -*.gz
46 -
47 -pids
48 -logs
49 -results
50 -
51 -node_modules
52 -npm-debug.log
53 -
54 -# Components #
55 -##############
56 -
57 -/build
58 -/components
...\ No newline at end of file ...\ No newline at end of file
1 -language: node_js
2 -node_js:
3 - - "0.4"
4 - - "0.6"
5 - - "0.8"
6 - - "0.10"
...\ No newline at end of file ...\ No newline at end of file
1 -# Array Series [![Build Status](https://travis-ci.org/component/array-parallel.png)](https://travis-ci.org/component/array-parallel)
2 -
3 -Call an array of asynchronous functions in parallel
4 -
5 -### API
6 -
7 -#### parallel(fns[, context[, callback]])
8 -
9 -```js
10 -var parallel = require('array-parallel')
11 -
12 -parallel([
13 - function (done) {
14 - done()
15 - }
16 -], this, function (err) {
17 -
18 -})
19 -```
20 -
21 -#### fns
22 -
23 -`fns` is an array of functions to call in parallel.
24 -The argument signature should be:
25 -
26 -```js
27 -function (done) {
28 - done(new Error())
29 - // or
30 - done(null, result)
31 -}
32 -```
33 -
34 -That is, each function should only take a `done` as an argument.
35 -Each callback should only take an `Error` as the first argument,
36 -or a value as the second.
37 -
38 -#### context
39 -
40 -Optional context to pass to each `fn`.
41 -Basically `fn.call(context, done)`.
42 -
43 -#### callback(err, results)
44 -
45 -```js
46 -function (err, results) {
47 -
48 -}
49 -```
50 -
51 -Only argument is an `Error` argument.
52 -It will be the first error retrieved from all the `fns`.
53 -`results` will be an array of results from each `fn`,
54 -thus this could be considered an asynchronous version of `[].map`.
55 -
56 -### License
57 -
58 -The MIT License (MIT)
59 -
60 -Copyright (c) 2013 Jonathan Ong me@jongleberry.com
61 -
62 -Permission is hereby granted, free of charge, to any person obtaining a copy
63 -of this software and associated documentation files (the "Software"), to deal
64 -in the Software without restriction, including without limitation the rights
65 -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
66 -copies of the Software, and to permit persons to whom the Software is
67 -furnished to do so, subject to the following conditions:
68 -
69 -The above copyright notice and this permission notice shall be included in
70 -all copies or substantial portions of the Software.
71 -
72 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74 -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75 -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76 -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
77 -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
78 -THE SOFTWARE.
1 -{
2 - "name": "array-parallel",
3 - "description": "Call an array of asynchronous functions in parallel",
4 - "repo": "array-parallel",
5 - "version": "0.1.3",
6 - "main": "index.js",
7 - "scripts": [
8 - "index.js"
9 - ],
10 - "license": "MIT"
11 -}
...\ No newline at end of file ...\ No newline at end of file
1 -module.exports = function parallel(fns, context, callback) {
2 - if (!callback) {
3 - if (typeof context === 'function') {
4 - callback = context
5 - context = null
6 - } else {
7 - callback = noop
8 - }
9 - }
10 -
11 - var pending = fns && fns.length
12 - if (!pending) return callback(null, []);
13 -
14 - var finished = false
15 - var results = new Array(pending)
16 -
17 - fns.forEach(context ? function (fn, i) {
18 - fn.call(context, maybeDone(i))
19 - } : function (fn, i) {
20 - fn(maybeDone(i))
21 - })
22 -
23 - function maybeDone(i) {
24 - return function (err, result) {
25 - if (finished) return;
26 -
27 - if (err) {
28 - callback(err, results)
29 - finished = true
30 - return
31 - }
32 -
33 - results[i] = result
34 -
35 - if (!--pending) callback(null, results);
36 - }
37 - }
38 -}
39 -
40 -function noop() {}
1 -{
2 - "name": "array-parallel",
3 - "description": "Call an array of asynchronous functions in parallel",
4 - "version": "0.1.3",
5 - "scripts": {
6 - "test": "node test"
7 - },
8 - "author": {
9 - "name": "Jonathan Ong",
10 - "email": "me@jongleberry.com",
11 - "url": "http://jongleberry.com"
12 - },
13 - "repository": {
14 - "type": "git",
15 - "url": "https://github.com/component/array-parallel.git"
16 - },
17 - "bugs": {
18 - "url": "https://github.com/component/array-parallel/issues",
19 - "email": "me@jongleberry.com"
20 - },
21 - "license": "MIT",
22 - "homepage": "https://github.com/component/array-parallel",
23 - "_id": "array-parallel@0.1.3",
24 - "dist": {
25 - "shasum": "8f785308926ed5aa478c47e64d1b334b6c0c947d",
26 - "tarball": "http://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz"
27 - },
28 - "_from": "array-parallel@~0.1.0",
29 - "_npmVersion": "1.3.17",
30 - "_npmUser": {
31 - "name": "jongleberry",
32 - "email": "jonathanrichardong@gmail.com"
33 - },
34 - "maintainers": [
35 - {
36 - "name": "jongleberry",
37 - "email": "jonathanrichardong@gmail.com"
38 - }
39 - ],
40 - "directories": {},
41 - "_shasum": "8f785308926ed5aa478c47e64d1b334b6c0c947d",
42 - "_resolved": "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz"
43 -}
1 -var assert = require('assert')
2 -var parallel = require('./')
3 -
4 -var a, b, c
5 -parallel([
6 - function (done) {
7 - setTimeout(function () {
8 - done(null, a = 0)
9 - }, 5)
10 - },
11 - function (done) {
12 - setTimeout(function () {
13 - done(null, b = 1)
14 - }, 10)
15 - },
16 - function (done) {
17 - setTimeout(function () {
18 - done(null, c = 2)
19 - }, 15)
20 - }
21 -], function (err, results) {
22 - assert.equal(a, 0)
23 - assert.equal(b, 1)
24 - assert.equal(c, 2)
25 -
26 - assert.deepEqual(results, [0, 1, 2])
27 -})
28 -
29 -var d, e
30 -parallel([
31 - function (done) {
32 - setTimeout(function () {
33 - d = 1
34 - done(new Error('message'))
35 - }, 5)
36 - },
37 - function (done) {
38 - setTimeout(function () {
39 - e = 2
40 - done()
41 - }, 10)
42 - }
43 -], function (err) {
44 - assert.equal(err.message, 'message')
45 - assert.equal(d, 1)
46 - assert.equal(e, undefined)
47 -})
48 -
49 -var context = 'hello'
50 -parallel([function (done) {
51 - assert.equal(this, context)
52 -}], context)
53 -
54 -var f
55 -parallel([function (done) {
56 - f = true
57 - done()
58 -}])
59 -
60 -process.nextTick(function () {
61 - assert.equal(f, true)
62 -})
...\ No newline at end of file ...\ No newline at end of file
1 -# Compiled source #
2 -###################
3 -*.com
4 -*.class
5 -*.dll
6 -*.exe
7 -*.o
8 -*.so
9 -
10 -# Packages #
11 -############
12 -# it's better to unpack these files and commit the raw source
13 -# git has its own built in compression methods
14 -*.7z
15 -*.dmg
16 -*.gz
17 -*.iso
18 -*.jar
19 -*.rar
20 -*.tar
21 -*.zip
22 -
23 -# Logs and databases #
24 -######################
25 -*.log
26 -*.sql
27 -*.sqlite
28 -
29 -# OS generated files #
30 -######################
31 -.DS_Store*
32 -ehthumbs.db
33 -Icon?
34 -Thumbs.db
35 -
36 -# Node.js #
37 -###########
38 -lib-cov
39 -*.seed
40 -*.log
41 -*.csv
42 -*.dat
43 -*.out
44 -*.pid
45 -*.gz
46 -
47 -pids
48 -logs
49 -results
50 -
51 -node_modules
52 -npm-debug.log
53 -
54 -# Components #
55 -##############
56 -
57 -/build
58 -/components
...\ No newline at end of file ...\ No newline at end of file
1 -language: node_js
2 -node_js:
3 - - "0.8"
4 - - "0.10"
...\ No newline at end of file ...\ No newline at end of file
1 -# Array Series [![Build Status](https://travis-ci.org/component/array-series.png)](https://travis-ci.org/component/array-series)
2 -
3 -Call an array of asynchronous functions in series
4 -
5 -### API
6 -
7 -#### series(fns[, context[, callback]])
8 -
9 -```js
10 -var series = require('array-series')
11 -
12 -series([
13 - function (done) {
14 - done()
15 - }
16 -], this, function (err) {
17 -
18 -})
19 -```
20 -
21 -#### fns
22 -
23 -`fns` is an array of functions to call in series.
24 -The argument signature should be:
25 -
26 -```js
27 -function (done) {
28 - done(new Error())
29 - // or
30 - done()
31 -}
32 -```
33 -
34 -That is, each function should only take a `done` as an argument.
35 -Each callback should only take an optional `Error` as an argument.
36 -
37 -#### context
38 -
39 -Optional context to pass to each `fn`.
40 -Basically `fn.call(context, done)`.
41 -
42 -#### callback(err)
43 -
44 -```js
45 -function (err) {
46 -
47 -}
48 -```
49 -
50 -Only argument is an `Error` argument.
51 -It will return the first error in the series of functions that returns an error,
52 -and no function after will be called.
53 -
54 -### License
55 -
56 -The MIT License (MIT)
57 -
58 -Copyright (c) 2013 Jonathan Ong me@jongleberry.com
59 -
60 -Permission is hereby granted, free of charge, to any person obtaining a copy
61 -of this software and associated documentation files (the "Software"), to deal
62 -in the Software without restriction, including without limitation the rights
63 -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
64 -copies of the Software, and to permit persons to whom the Software is
65 -furnished to do so, subject to the following conditions:
66 -
67 -The above copyright notice and this permission notice shall be included in
68 -all copies or substantial portions of the Software.
69 -
70 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
72 -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
73 -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74 -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75 -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
76 -THE SOFTWARE.
...\ No newline at end of file ...\ No newline at end of file
1 -{
2 - "name": "array-series",
3 - "description": "Call an array of asynchronous functions in series",
4 - "repo": "component/array-series",
5 - "version": "0.1.5",
6 - "main": "index.js",
7 - "scripts": [
8 - "index.js"
9 - ],
10 - "license": "MIT"
11 -}
...\ No newline at end of file ...\ No newline at end of file
1 -module.exports = function series(fns, context, callback) {
2 - if (!callback) {
3 - if (typeof context === 'function') {
4 - callback = context
5 - context = null
6 - } else {
7 - callback = noop
8 - }
9 - }
10 -
11 - if (!(fns && fns.length)) return callback();
12 -
13 - fns = fns.slice(0)
14 -
15 - var call = context
16 - ? function () {
17 - fns.length
18 - ? fns.shift().call(context, next)
19 - : callback()
20 - }
21 - : function () {
22 - fns.length
23 - ? fns.shift()(next)
24 - : callback()
25 - }
26 -
27 - call()
28 -
29 - function next(err) {
30 - err ? callback(err) : call()
31 - }
32 -}
33 -
34 -function noop() {}
1 -{
2 - "name": "array-series",
3 - "description": "Call an array of asynchronous functions in series",
4 - "version": "0.1.5",
5 - "scripts": {
6 - "test": "node test"
7 - },
8 - "author": {
9 - "name": "Jonathan Ong",
10 - "email": "me@jongleberry.com",
11 - "url": "http://jongleberry.com"
12 - },
13 - "repository": {
14 - "type": "git",
15 - "url": "https://github.com/component/array-series.git"
16 - },
17 - "bugs": {
18 - "url": "https://github.com/component/array-series/issues",
19 - "email": "me@jongleberry.com"
20 - },
21 - "license": "MIT",
22 - "homepage": "https://github.com/component/array-series",
23 - "_id": "array-series@0.1.5",
24 - "dist": {
25 - "shasum": "df5d37bfc5c2ef0755e2aa4f92feae7d4b5a972f",
26 - "tarball": "http://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz"
27 - },
28 - "_from": "array-series@~0.1.0",
29 - "_npmVersion": "1.3.17",
30 - "_npmUser": {
31 - "name": "jongleberry",
32 - "email": "jonathanrichardong@gmail.com"
33 - },
34 - "maintainers": [
35 - {
36 - "name": "jongleberry",
37 - "email": "jonathanrichardong@gmail.com"
38 - }
39 - ],
40 - "directories": {},
41 - "_shasum": "df5d37bfc5c2ef0755e2aa4f92feae7d4b5a972f",
42 - "_resolved": "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz"
43 -}
1 -var assert = require('assert')
2 -var series = require('./')
3 -
4 -var a, b, c
5 -
6 -series([
7 - function (done) {
8 - a = 1
9 - process.nextTick(done)
10 - check('a')
11 - },
12 - function (done) {
13 - b = 2
14 - process.nextTick(done)
15 - check('b')
16 - },
17 - function (done) {
18 - c = 3
19 - process.nextTick(done)
20 - check('c')
21 - }
22 -], function (err) {
23 - assert.ifError(err)
24 - assert.equal(a, 1)
25 - assert.equal(b, 2)
26 - assert.equal(c, 3)
27 -})
28 -
29 -function check(x) {
30 - switch (x) {
31 - case 'a':
32 - assert.equal(a, 1)
33 - assert.equal(b, undefined)
34 - assert.equal(c, undefined)
35 - break
36 - case 'b':
37 - assert.equal(a, 1)
38 - assert.equal(b, 2)
39 - assert.equal(c, undefined)
40 - break
41 - case 'c':
42 - assert.equal(a, 1)
43 - assert.equal(b, 2)
44 - assert.equal(c, 3)
45 - break
46 - }
47 -}
48 -
49 -var context = 'hello'
50 -series([function (done) {
51 - assert.equal(this, context)
52 - done()
53 -}], context)
54 -
55 -var finished
56 -series([], function (err) {
57 - finished = true
58 -})
59 -
60 -process.nextTick(function () {
61 - if (!finished)
62 - throw new Error('Failed with no functions.');
63 -})
64 -
65 -var r, d, o
66 -series([
67 - function (done) {
68 - r = 1
69 - process.nextTick(done)
70 - },
71 - function (done) {
72 - d = 0
73 - process.nextTick(function () {
74 - done(new Error('message'))
75 - })
76 - },
77 - function (done) {
78 - o = 0
79 - process.nextTick(done)
80 - }
81 -], function (err) {
82 - assert.equal(err.message, 'message')
83 - assert.equal(r, 1)
84 - assert.equal(d, 0)
85 - assert.equal(o, undefined)
86 -})
87 -
88 -console.log('Array series tests pass!')
...\ No newline at end of file ...\ No newline at end of file
1 -
2 -0.7.0 / 2012-05-04
3 -==================
4 -
5 - * Added .component to package.json
6 - * Added debug.component.js build
7 -
8 -0.6.0 / 2012-03-16
9 -==================
10 -
11 - * Added support for "-" prefix in DEBUG [Vinay Pulim]
12 - * Added `.enabled` flag to the node version [TooTallNate]
13 -
14 -0.5.0 / 2012-02-02
15 -==================
16 -
17 - * Added: humanize diffs. Closes #8
18 - * Added `debug.disable()` to the CS variant
19 - * Removed padding. Closes #10
20 - * Fixed: persist client-side variant again. Closes #9
21 -
22 -0.4.0 / 2012-02-01
23 -==================
24 -
25 - * Added browser variant support for older browsers [TooTallNate]
26 - * Added `debug.enable('project:*')` to browser variant [TooTallNate]
27 - * Added padding to diff (moved it to the right)
28 -
29 -0.3.0 / 2012-01-26
30 -==================
31 -
32 - * Added millisecond diff when isatty, otherwise UTC string
33 -
34 -0.2.0 / 2012-01-22
35 -==================
36 -
37 - * Added wildcard support
38 -
39 -0.1.0 / 2011-12-02
40 -==================
41 -
42 - * Added: remove colors unless stderr isatty [TooTallNate]
43 -
44 -0.0.1 / 2010-01-03
45 -==================
46 -
47 - * Initial release
1 -
2 -debug.component.js: head.js debug.js tail.js
3 - cat $^ > $@
4 -
1 -
2 -# debug
3 -
4 - tiny node.js debugging utility.
5 -
6 -## Installation
7 -
8 -```
9 -$ npm install debug
10 -```
11 -
12 -## Example
13 -
14 - This module is modelled after node core's debugging technique, allowing you to enable one or more topic-specific debugging functions, for example core does the following within many modules:
15 -
16 -```js
17 -var debug;
18 -if (process.env.NODE_DEBUG && /cluster/.test(process.env.NODE_DEBUG)) {
19 - debug = function(x) {
20 - var prefix = process.pid + ',' +
21 - (process.env.NODE_WORKER_ID ? 'Worker' : 'Master');
22 - console.error(prefix, x);
23 - };
24 -} else {
25 - debug = function() { };
26 -}
27 -```
28 -
29 - This concept is extremely simple but it works well. With `debug` you simply invoke the exported function to generate your debug function, passing it a name which will determine if a noop function is returned, or a decorated `console.error`, so all of the `console` format string goodies you're used to work fine. A unique color is selected per-function for visibility.
30 -
31 -Example _app.js_:
32 -
33 -```js
34 -var debug = require('debug')('http')
35 - , http = require('http')
36 - , name = 'My App';
37 -
38 -// fake app
39 -
40 -debug('booting %s', name);
41 -
42 -http.createServer(function(req, res){
43 - debug(req.method + ' ' + req.url);
44 - res.end('hello\n');
45 -}).listen(3000, function(){
46 - debug('listening');
47 -});
48 -
49 -// fake worker of some kind
50 -
51 -require('./worker');
52 -```
53 -
54 -Example _worker.js_:
55 -
56 -```js
57 -var debug = require('debug')('worker');
58 -
59 -setInterval(function(){
60 - debug('doing some work');
61 -}, 1000);
62 -```
63 -
64 - The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
65 -
66 - ![debug http and worker](http://f.cl.ly/items/18471z1H402O24072r1J/Screenshot.png)
67 -
68 - ![debug worker](http://f.cl.ly/items/1X413v1a3M0d3C2c1E0i/Screenshot.png)
69 -
70 -## Millisecond diff
71 -
72 - When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
73 -
74 - ![](http://f.cl.ly/items/2i3h1d3t121M2Z1A3Q0N/Screenshot.png)
75 -
76 - When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
77 -
78 - ![](http://f.cl.ly/items/112H3i0e0o0P0a2Q2r11/Screenshot.png)
79 -
80 -## Conventions
81 -
82 - If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
83 -
84 -## Wildcards
85 -
86 - The "*" character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect.compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
87 -
88 - You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=* -connect:*` would include all debuggers except those starting with "connect:".
89 -
90 -## Browser support
91 -
92 - Debug works in the browser as well, currently persisted by `localStorage`. For example if you have `worker:a` and `worker:b` as shown below, and wish to debug both type `debug.enable('worker:*')` in the console and refresh the page, this will remain until you disable with `debug.disable()`.
93 -
94 -```js
95 -a = debug('worker:a');
96 -b = debug('worker:b');
97 -
98 -setInterval(function(){
99 - a('doing some work');
100 -}, 1000);
101 -
102 -setInterval(function(){
103 - a('doing some work');
104 -}, 1200);
105 -```
106 -
107 -## License
108 -
109 -(The MIT License)
110 -
111 -Copyright (c) 2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
112 -
113 -Permission is hereby granted, free of charge, to any person obtaining
114 -a copy of this software and associated documentation files (the
115 -'Software'), to deal in the Software without restriction, including
116 -without limitation the rights to use, copy, modify, merge, publish,
117 -distribute, sublicense, and/or sell copies of the Software, and to
118 -permit persons to whom the Software is furnished to do so, subject to
119 -the following conditions:
120 -
121 -The above copyright notice and this permission notice shall be
122 -included in all copies or substantial portions of the Software.
123 -
124 -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
125 -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
126 -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
127 -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
128 -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
129 -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
130 -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
...\ No newline at end of file ...\ No newline at end of file
1 -;(function(){
2 -
3 -/**
4 - * Create a debugger with the given `name`.
5 - *
6 - * @param {String} name
7 - * @return {Type}
8 - * @api public
9 - */
10 -
11 -function debug(name) {
12 - if (!debug.enabled(name)) return function(){};
13 -
14 - return function(fmt){
15 - var curr = new Date;
16 - var ms = curr - (debug[name] || curr);
17 - debug[name] = curr;
18 -
19 - fmt = name
20 - + ' '
21 - + fmt
22 - + ' +' + debug.humanize(ms);
23 -
24 - // This hackery is required for IE8
25 - // where `console.log` doesn't have 'apply'
26 - window.console
27 - && console.log
28 - && Function.prototype.apply.call(console.log, console, arguments);
29 - }
30 -}
31 -
32 -/**
33 - * The currently active debug mode names.
34 - */
35 -
36 -debug.names = [];
37 -debug.skips = [];
38 -
39 -/**
40 - * Enables a debug mode by name. This can include modes
41 - * separated by a colon and wildcards.
42 - *
43 - * @param {String} name
44 - * @api public
45 - */
46 -
47 -debug.enable = function(name) {
48 - localStorage.debug = name;
49 -
50 - var split = (name || '').split(/[\s,]+/)
51 - , len = split.length;
52 -
53 - for (var i = 0; i < len; i++) {
54 - name = split[i].replace('*', '.*?');
55 - if (name[0] === '-') {
56 - debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
57 - }
58 - else {
59 - debug.names.push(new RegExp('^' + name + '$'));
60 - }
61 - }
62 -};
63 -
64 -/**
65 - * Disable debug output.
66 - *
67 - * @api public
68 - */
69 -
70 -debug.disable = function(){
71 - debug.enable('');
72 -};
73 -
74 -/**
75 - * Humanize the given `ms`.
76 - *
77 - * @param {Number} m
78 - * @return {String}
79 - * @api private
80 - */
81 -
82 -debug.humanize = function(ms) {
83 - var sec = 1000
84 - , min = 60 * 1000
85 - , hour = 60 * min;
86 -
87 - if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
88 - if (ms >= min) return (ms / min).toFixed(1) + 'm';
89 - if (ms >= sec) return (ms / sec | 0) + 's';
90 - return ms + 'ms';
91 -};
92 -
93 -/**
94 - * Returns true if the given mode name is enabled, false otherwise.
95 - *
96 - * @param {String} name
97 - * @return {Boolean}
98 - * @api public
99 - */
100 -
101 -debug.enabled = function(name) {
102 - for (var i = 0, len = debug.skips.length; i < len; i++) {
103 - if (debug.skips[i].test(name)) {
104 - return false;
105 - }
106 - }
107 - for (var i = 0, len = debug.names.length; i < len; i++) {
108 - if (debug.names[i].test(name)) {
109 - return true;
110 - }
111 - }
112 - return false;
113 -};
114 -
115 -// persist
116 -
117 -if (window.localStorage) debug.enable(localStorage.debug);
118 - module.exports = debug;
119 -
120 -})();
...\ No newline at end of file ...\ No newline at end of file
1 -
2 -/**
3 - * Create a debugger with the given `name`.
4 - *
5 - * @param {String} name
6 - * @return {Type}
7 - * @api public
8 - */
9 -
10 -function debug(name) {
11 - if (!debug.enabled(name)) return function(){};
12 -
13 - return function(fmt){
14 - var curr = new Date;
15 - var ms = curr - (debug[name] || curr);
16 - debug[name] = curr;
17 -
18 - fmt = name
19 - + ' '
20 - + fmt
21 - + ' +' + debug.humanize(ms);
22 -
23 - // This hackery is required for IE8
24 - // where `console.log` doesn't have 'apply'
25 - window.console
26 - && console.log
27 - && Function.prototype.apply.call(console.log, console, arguments);
28 - }
29 -}
30 -
31 -/**
32 - * The currently active debug mode names.
33 - */
34 -
35 -debug.names = [];
36 -debug.skips = [];
37 -
38 -/**
39 - * Enables a debug mode by name. This can include modes
40 - * separated by a colon and wildcards.
41 - *
42 - * @param {String} name
43 - * @api public
44 - */
45 -
46 -debug.enable = function(name) {
47 - localStorage.debug = name;
48 -
49 - var split = (name || '').split(/[\s,]+/)
50 - , len = split.length;
51 -
52 - for (var i = 0; i < len; i++) {
53 - name = split[i].replace('*', '.*?');
54 - if (name[0] === '-') {
55 - debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
56 - }
57 - else {
58 - debug.names.push(new RegExp('^' + name + '$'));
59 - }
60 - }
61 -};
62 -
63 -/**
64 - * Disable debug output.
65 - *
66 - * @api public
67 - */
68 -
69 -debug.disable = function(){
70 - debug.enable('');
71 -};
72 -
73 -/**
74 - * Humanize the given `ms`.
75 - *
76 - * @param {Number} m
77 - * @return {String}
78 - * @api private
79 - */
80 -
81 -debug.humanize = function(ms) {
82 - var sec = 1000
83 - , min = 60 * 1000
84 - , hour = 60 * min;
85 -
86 - if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
87 - if (ms >= min) return (ms / min).toFixed(1) + 'm';
88 - if (ms >= sec) return (ms / sec | 0) + 's';
89 - return ms + 'ms';
90 -};
91 -
92 -/**
93 - * Returns true if the given mode name is enabled, false otherwise.
94 - *
95 - * @param {String} name
96 - * @return {Boolean}
97 - * @api public
98 - */
99 -
100 -debug.enabled = function(name) {
101 - for (var i = 0, len = debug.skips.length; i < len; i++) {
102 - if (debug.skips[i].test(name)) {
103 - return false;
104 - }
105 - }
106 - for (var i = 0, len = debug.names.length; i < len; i++) {
107 - if (debug.names[i].test(name)) {
108 - return true;
109 - }
110 - }
111 - return false;
112 -};
113 -
114 -// persist
115 -
116 -if (window.localStorage) debug.enable(localStorage.debug);
...\ No newline at end of file ...\ No newline at end of file
1 -
2 -var debug = require('../')('http')
3 - , http = require('http')
4 - , name = 'My App';
5 -
6 -// fake app
7 -
8 -debug('booting %s', name);
9 -
10 -http.createServer(function(req, res){
11 - debug(req.method + ' ' + req.url);
12 - res.end('hello\n');
13 -}).listen(3000, function(){
14 - debug('listening');
15 -});
16 -
17 -// fake worker of some kind
18 -
19 -require('./worker');
...\ No newline at end of file ...\ No newline at end of file
1 -<html>
2 - <head>
3 - <title>debug()</title>
4 - <script src="../debug.js"></script>
5 - <script>
6 - // type debug.enable('*') in
7 - // the console and refresh :)
8 -
9 - a = debug('worker:a');
10 - b = debug('worker:b');
11 -
12 - setInterval(function(){
13 - a('doing some work');
14 - }, 1000);
15 -
16 - setInterval(function(){
17 - a('doing some work');
18 - }, 1200);
19 - </script>
20 - </head>
21 - <body>
22 -
23 - </body>
24 -</html>
1 -
2 -var debug = {
3 - foo: require('../')('test:foo'),
4 - bar: require('../')('test:bar'),
5 - baz: require('../')('test:baz')
6 -};
7 -
8 -debug.foo('foo')
9 -debug.bar('bar')
10 -debug.baz('baz')
...\ No newline at end of file ...\ No newline at end of file
1 -
2 -// DEBUG=* node example/worker
3 -// DEBUG=worker:* node example/worker
4 -// DEBUG=worker:a node example/worker
5 -// DEBUG=worker:b node example/worker
6 -
7 -var a = require('../')('worker:a')
8 - , b = require('../')('worker:b');
9 -
10 -function work() {
11 - a('doing lots of uninteresting work');
12 - setTimeout(work, Math.random() * 1000);
13 -}
14 -
15 -work();
16 -
17 -function workb() {
18 - b('doing some work');
19 - setTimeout(workb, Math.random() * 2000);
20 -}
21 -
22 -workb();
...\ No newline at end of file ...\ No newline at end of file
1 -
2 -module.exports = require('./lib/debug');
...\ No newline at end of file ...\ No newline at end of file
1 -{
2 - "name": "debug",
3 - "version": "0.7.0",
4 - "description": "small debugging utility",
5 - "keywords": [
6 - "debug",
7 - "log",
8 - "debugger"
9 - ],
10 - "author": {
11 - "name": "TJ Holowaychuk",
12 - "email": "tj@vision-media.ca"
13 - },
14 - "dependencies": {},
15 - "devDependencies": {
16 - "mocha": "*"
17 - },
18 - "main": "index",
19 - "browserify": "debug.component.js",
20 - "engines": {
21 - "node": "*"
22 - },
23 - "component": {
24 - "scripts": {
25 - "debug": "debug.component.js"
26 - }
27 - },
28 - "_id": "debug@0.7.0",
29 - "dist": {
30 - "shasum": "f5be05ec0434c992d79940e50b2695cfb2e01b08",
31 - "tarball": "http://registry.npmjs.org/debug/-/debug-0.7.0.tgz"
32 - },
33 - "maintainers": [
34 - {
35 - "name": "tjholowaychuk",
36 - "email": "tj@vision-media.ca"
37 - }
38 - ],
39 - "directories": {},
40 - "_shasum": "f5be05ec0434c992d79940e50b2695cfb2e01b08",
41 - "_from": "debug@0.7.0",
42 - "_resolved": "https://registry.npmjs.org/debug/-/debug-0.7.0.tgz"
43 -}
1 -
2 - module.exports = debug;
3 -
4 -})();
...\ No newline at end of file ...\ No newline at end of file
1 -language: node_js
2 -node_js:
3 - - 0.6
4 - - 0.8
5 - - "0.10"
1 -Apache License, Version 2.0
2 -
3 -Copyright (c) 2011 Dominic Tarr
4 -
5 -Licensed under the Apache License, Version 2.0 (the "License");
6 -you may not use this file except in compliance with the License.
7 -You may obtain a copy of the License at
8 -
9 - http://www.apache.org/licenses/LICENSE-2.0
10 -
11 -Unless required by applicable law or agreed to in writing, software
12 -distributed under the License is distributed on an "AS IS" BASIS,
13 -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 -See the License for the specific language governing permissions and
15 -limitations under the License.
1 -The MIT License
2 -
3 -Copyright (c) 2011 Dominic Tarr
4 -
5 -Permission is hereby granted, free of charge,
6 -to any person obtaining a copy of this software and
7 -associated documentation files (the "Software"), to
8 -deal in the Software without restriction, including
9 -without limitation the rights to use, copy, modify,
10 -merge, publish, distribute, sublicense, and/or sell
11 -copies of the Software, and to permit persons to whom
12 -the Software is furnished to do so,
13 -subject to the following conditions:
14 -
15 -The above copyright notice and this permission notice
16 -shall be included in all copies or substantial portions of the Software.
17 -
18 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22 -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 -var Stream = require('stream')
2 -
3 -// through
4 -//
5 -// a stream that does nothing but re-emit the input.
6 -// useful for aggregating a series of changing but not ending streams into one stream)
7 -
8 -exports = module.exports = through
9 -through.through = through
10 -
11 -//create a readable writable stream.
12 -
13 -function through (write, end, opts) {
14 - write = write || function (data) { this.queue(data) }
15 - end = end || function () { this.queue(null) }
16 -
17 - var ended = false, destroyed = false, buffer = [], _ended = false
18 - var stream = new Stream()
19 - stream.readable = stream.writable = true
20 - stream.paused = false
21 -
22 -// stream.autoPause = !(opts && opts.autoPause === false)
23 - stream.autoDestroy = !(opts && opts.autoDestroy === false)
24 -
25 - stream.write = function (data) {
26 - write.call(this, data)
27 - return !stream.paused
28 - }
29 -
30 - function drain() {
31 - while(buffer.length && !stream.paused) {
32 - var data = buffer.shift()
33 - if(null === data)
34 - return stream.emit('end')
35 - else
36 - stream.emit('data', data)
37 - }
38 - }
39 -
40 - stream.queue = stream.push = function (data) {
41 -// console.error(ended)
42 - if(_ended) return stream
43 - if(data == null) _ended = true
44 - buffer.push(data)
45 - drain()
46 - return stream
47 - }
48 -
49 - //this will be registered as the first 'end' listener
50 - //must call destroy next tick, to make sure we're after any
51 - //stream piped from here.
52 - //this is only a problem if end is not emitted synchronously.
53 - //a nicer way to do this is to make sure this is the last listener for 'end'
54 -
55 - stream.on('end', function () {
56 - stream.readable = false
57 - if(!stream.writable && stream.autoDestroy)
58 - process.nextTick(function () {
59 - stream.destroy()
60 - })
61 - })
62 -
63 - function _end () {
64 - stream.writable = false
65 - end.call(stream)
66 - if(!stream.readable && stream.autoDestroy)
67 - stream.destroy()
68 - }
69 -
70 - stream.end = function (data) {
71 - if(ended) return
72 - ended = true
73 - if(arguments.length) stream.write(data)
74 - _end() // will emit or queue
75 - return stream
76 - }
77 -
78 - stream.destroy = function () {
79 - if(destroyed) return
80 - destroyed = true
81 - ended = true
82 - buffer.length = 0
83 - stream.writable = stream.readable = false
84 - stream.emit('close')
85 - return stream
86 - }
87 -
88 - stream.pause = function () {
89 - if(stream.paused) return
90 - stream.paused = true
91 - return stream
92 - }
93 -
94 - stream.resume = function () {
95 - if(stream.paused) {
96 - stream.paused = false
97 - stream.emit('resume')
98 - }
99 - drain()
100 - //may have become paused again,
101 - //as drain emits 'data'.
102 - if(!stream.paused)
103 - stream.emit('drain')
104 - return stream
105 - }
106 - return stream
107 -}
108 -
1 -{
2 - "name": "through",
3 - "version": "2.3.6",
4 - "description": "simplified stream construction",
5 - "main": "index.js",
6 - "scripts": {
7 - "test": "set -e; for t in test/*.js; do node $t; done"
8 - },
9 - "devDependencies": {
10 - "stream-spec": "~0.3.5",
11 - "tape": "~2.3.2",
12 - "from": "~0.1.3"
13 - },
14 - "keywords": [
15 - "stream",
16 - "streams",
17 - "user-streams",
18 - "pipe"
19 - ],
20 - "author": {
21 - "name": "Dominic Tarr",
22 - "email": "dominic.tarr@gmail.com",
23 - "url": "dominictarr.com"
24 - },
25 - "license": "MIT",
26 - "repository": {
27 - "type": "git",
28 - "url": "https://github.com/dominictarr/through.git"
29 - },
30 - "homepage": "http://github.com/dominictarr/through",
31 - "testling": {
32 - "browsers": [
33 - "ie/8..latest",
34 - "ff/15..latest",
35 - "chrome/20..latest",
36 - "safari/5.1..latest"
37 - ],
38 - "files": "test/*.js"
39 - },
40 - "gitHead": "19ed9b7e84efe7c3e3c8be80f29390b1620e13c0",
41 - "bugs": {
42 - "url": "https://github.com/dominictarr/through/issues"
43 - },
44 - "_id": "through@2.3.6",
45 - "_shasum": "26681c0f524671021d4e29df7c36bce2d0ecf2e8",
46 - "_from": "through@~2.3.1",
47 - "_npmVersion": "1.4.26",
48 - "_npmUser": {
49 - "name": "dominictarr",
50 - "email": "dominic.tarr@gmail.com"
51 - },
52 - "maintainers": [
53 - {
54 - "name": "dominictarr",
55 - "email": "dominic.tarr@gmail.com"
56 - }
57 - ],
58 - "dist": {
59 - "shasum": "26681c0f524671021d4e29df7c36bce2d0ecf2e8",
60 - "tarball": "http://registry.npmjs.org/through/-/through-2.3.6.tgz"
61 - },
62 - "directories": {},
63 - "_resolved": "https://registry.npmjs.org/through/-/through-2.3.6.tgz"
64 -}
1 -#through
2 -
3 -[![build status](https://secure.travis-ci.org/dominictarr/through.png)](http://travis-ci.org/dominictarr/through)
4 -[![testling badge](https://ci.testling.com/dominictarr/through.png)](https://ci.testling.com/dominictarr/through)
5 -
6 -Easy way to create a `Stream` that is both `readable` and `writable`.
7 -
8 -* Pass in optional `write` and `end` methods.
9 -* `through` takes care of pause/resume logic if you use `this.queue(data)` instead of `this.emit('data', data)`.
10 -* Use `this.pause()` and `this.resume()` to manage flow.
11 -* Check `this.paused` to see current flow state. (`write` always returns `!this.paused`).
12 -
13 -This function is the basis for most of the synchronous streams in
14 -[event-stream](http://github.com/dominictarr/event-stream).
15 -
16 -``` js
17 -var through = require('through')
18 -
19 -through(function write(data) {
20 - this.queue(data) //data *must* not be null
21 - },
22 - function end () { //optional
23 - this.queue(null)
24 - })
25 -```
26 -
27 -Or, can also be used _without_ buffering on pause, use `this.emit('data', data)`,
28 -and this.emit('end')
29 -
30 -``` js
31 -var through = require('through')
32 -
33 -through(function write(data) {
34 - this.emit('data', data)
35 - //this.pause()
36 - },
37 - function end () { //optional
38 - this.emit('end')
39 - })
40 -```
41 -
42 -## Extended Options
43 -
44 -You will probably not need these 99% of the time.
45 -
46 -### autoDestroy=false
47 -
48 -By default, `through` emits close when the writable
49 -and readable side of the stream has ended.
50 -If that is not desired, set `autoDestroy=false`.
51 -
52 -``` js
53 -var through = require('through')
54 -
55 -//like this
56 -var ts = through(write, end, {autoDestroy: false})
57 -//or like this
58 -var ts = through(write, end)
59 -ts.autoDestroy = false
60 -```
61 -
62 -## License
63 -
64 -MIT / Apache2
1 -var from = require('from')
2 -var through = require('../')
3 -
4 -var tape = require('tape')
5 -
6 -tape('simple async example', function (t) {
7 -
8 - var n = 0, expected = [1,2,3,4,5], actual = []
9 - from(expected)
10 - .pipe(through(function(data) {
11 - this.pause()
12 - n ++
13 - setTimeout(function(){
14 - console.log('pushing data', data)
15 - this.push(data)
16 - this.resume()
17 - }.bind(this), 300)
18 - })).pipe(through(function(data) {
19 - console.log('pushing data second time', data);
20 - this.push(data)
21 - })).on('data', function (d) {
22 - actual.push(d)
23 - }).on('end', function() {
24 - t.deepEqual(actual, expected)
25 - t.end()
26 - })
27 -
28 -})
1 -var test = require('tape')
2 -var through = require('../')
3 -
4 -// must emit end before close.
5 -
6 -test('end before close', function (assert) {
7 - var ts = through()
8 - ts.autoDestroy = false
9 - var ended = false, closed = false
10 -
11 - ts.on('end', function () {
12 - assert.ok(!closed)
13 - ended = true
14 - })
15 - ts.on('close', function () {
16 - assert.ok(ended)
17 - closed = true
18 - })
19 -
20 - ts.write(1)
21 - ts.write(2)
22 - ts.write(3)
23 - ts.end()
24 - assert.ok(ended)
25 - assert.notOk(closed)
26 - ts.destroy()
27 - assert.ok(closed)
28 - assert.end()
29 -})
30 -
1 -var test = require('tape')
2 -var through = require('../')
3 -
4 -// must emit end before close.
5 -
6 -test('buffering', function(assert) {
7 - var ts = through(function (data) {
8 - this.queue(data)
9 - }, function () {
10 - this.queue(null)
11 - })
12 -
13 - var ended = false, actual = []
14 -
15 - ts.on('data', actual.push.bind(actual))
16 - ts.on('end', function () {
17 - ended = true
18 - })
19 -
20 - ts.write(1)
21 - ts.write(2)
22 - ts.write(3)
23 - assert.deepEqual(actual, [1, 2, 3])
24 - ts.pause()
25 - ts.write(4)
26 - ts.write(5)
27 - ts.write(6)
28 - assert.deepEqual(actual, [1, 2, 3])
29 - ts.resume()
30 - assert.deepEqual(actual, [1, 2, 3, 4, 5, 6])
31 - ts.pause()
32 - ts.end()
33 - assert.ok(!ended)
34 - ts.resume()
35 - assert.ok(ended)
36 - assert.end()
37 -})
38 -
39 -test('buffering has data in queue, when ends', function (assert) {
40 -
41 - /*
42 - * If stream ends while paused with data in the queue,
43 - * stream should still emit end after all data is written
44 - * on resume.
45 - */
46 -
47 - var ts = through(function (data) {
48 - this.queue(data)
49 - }, function () {
50 - this.queue(null)
51 - })
52 -
53 - var ended = false, actual = []
54 -
55 - ts.on('data', actual.push.bind(actual))
56 - ts.on('end', function () {
57 - ended = true
58 - })
59 -
60 - ts.pause()
61 - ts.write(1)
62 - ts.write(2)
63 - ts.write(3)
64 - ts.end()
65 - assert.deepEqual(actual, [], 'no data written yet, still paused')
66 - assert.ok(!ended, 'end not emitted yet, still paused')
67 - ts.resume()
68 - assert.deepEqual(actual, [1, 2, 3], 'resumed, all data should be delivered')
69 - assert.ok(ended, 'end should be emitted once all data was delivered')
70 - assert.end();
71 -})
1 -var test = require('tape')
2 -var through = require('../')
3 -
4 -// must emit end before close.
5 -
6 -test('end before close', function (assert) {
7 - var ts = through()
8 - var ended = false, closed = false
9 -
10 - ts.on('end', function () {
11 - assert.ok(!closed)
12 - ended = true
13 - })
14 - ts.on('close', function () {
15 - assert.ok(ended)
16 - closed = true
17 - })
18 -
19 - ts.write(1)
20 - ts.write(2)
21 - ts.write(3)
22 - ts.end()
23 - assert.ok(ended)
24 - assert.ok(closed)
25 - assert.end()
26 -})
27 -
28 -test('end only once', function (t) {
29 -
30 - var ts = through()
31 - var ended = false, closed = false
32 -
33 - ts.on('end', function () {
34 - t.equal(ended, false)
35 - ended = true
36 - })
37 -
38 - ts.queue(null)
39 - ts.queue(null)
40 - ts.queue(null)
41 -
42 - ts.resume()
43 -
44 - t.end()
45 -})
1 -
2 -var test = require('tape')
3 -var spec = require('stream-spec')
4 -var through = require('../')
5 -
6 -/*
7 - I'm using these two functions, and not streams and pipe
8 - so there is less to break. if this test fails it must be
9 - the implementation of _through_
10 -*/
11 -
12 -function write(array, stream) {
13 - array = array.slice()
14 - function next() {
15 - while(array.length)
16 - if(stream.write(array.shift()) === false)
17 - return stream.once('drain', next)
18 -
19 - stream.end()
20 - }
21 -
22 - next()
23 -}
24 -
25 -function read(stream, callback) {
26 - var actual = []
27 - stream.on('data', function (data) {
28 - actual.push(data)
29 - })
30 - stream.once('end', function () {
31 - callback(null, actual)
32 - })
33 - stream.once('error', function (err) {
34 - callback(err)
35 - })
36 -}
37 -
38 -test('simple defaults', function(assert) {
39 -
40 - var l = 1000
41 - , expected = []
42 -
43 - while(l--) expected.push(l * Math.random())
44 -
45 - var t = through()
46 - var s = spec(t).through().pausable()
47 -
48 - read(t, function (err, actual) {
49 - assert.ifError(err)
50 - assert.deepEqual(actual, expected)
51 - assert.end()
52 - })
53 -
54 - t.on('close', s.validate)
55 -
56 - write(expected, t)
57 -});
58 -
59 -test('simple functions', function(assert) {
60 -
61 - var l = 1000
62 - , expected = []
63 -
64 - while(l--) expected.push(l * Math.random())
65 -
66 - var t = through(function (data) {
67 - this.emit('data', data*2)
68 - })
69 - var s = spec(t).through().pausable()
70 -
71 -
72 - read(t, function (err, actual) {
73 - assert.ifError(err)
74 - assert.deepEqual(actual, expected.map(function (data) {
75 - return data*2
76 - }))
77 - assert.end()
78 - })
79 -
80 - t.on('close', s.validate)
81 -
82 - write(expected, t)
83 -})
84 -
85 -test('pauses', function(assert) {
86 -
87 - var l = 1000
88 - , expected = []
89 -
90 - while(l--) expected.push(l) //Math.random())
91 -
92 - var t = through()
93 -
94 - var s = spec(t)
95 - .through()
96 - .pausable()
97 -
98 - t.on('data', function () {
99 - if(Math.random() > 0.1) return
100 - t.pause()
101 - process.nextTick(function () {
102 - t.resume()
103 - })
104 - })
105 -
106 - read(t, function (err, actual) {
107 - assert.ifError(err)
108 - assert.deepEqual(actual, expected)
109 - })
110 -
111 - t.on('close', function () {
112 - s.validate()
113 - assert.end()
114 - })
115 -
116 - write(expected, t)
117 -})
1 -{
2 - "name": "gm",
3 - "description": "GraphicsMagick and ImageMagick for node.js",
4 - "version": "1.17.0",
5 - "author": {
6 - "name": "Aaron Heckmann",
7 - "email": "aaron.heckmann+github@gmail.com"
8 - },
9 - "keywords": [
10 - "graphics",
11 - "magick",
12 - "image",
13 - "graphicsmagick",
14 - "imagemagick",
15 - "gm",
16 - "convert",
17 - "identify",
18 - "compare"
19 - ],
20 - "engines": {
21 - "node": ">= 0.8.0"
22 - },
23 - "bugs": {
24 - "url": "http://github.com/aheckmann/gm/issues"
25 - },
26 - "licenses": [
27 - {
28 - "type": "MIT",
29 - "url": "http://www.opensource.org/licenses/mit-license.php"
30 - }
31 - ],
32 - "main": "./index",
33 - "scripts": {
34 - "test": "make test-unit; make test;"
35 - },
36 - "repository": {
37 - "type": "git",
38 - "url": "https://github.com/aheckmann/gm.git"
39 - },
40 - "license": "MIT",
41 - "devDependencies": {
42 - "gleak": "0.4.0",
43 - "async": "~0.2.7"
44 - },
45 - "dependencies": {
46 - "debug": "0.7.0",
47 - "array-series": "~0.1.0",
48 - "array-parallel": "~0.1.0",
49 - "through": "~2.3.1"
50 - },
51 - "gitHead": "2fb65bac7c09ab8b09e87b791b146b82c209076e",
52 - "homepage": "https://github.com/aheckmann/gm",
53 - "_id": "gm@1.17.0",
54 - "_shasum": "27a261e0bdfee3d373d24b5a27bd249057355068",
55 - "_from": "gm@",
56 - "_npmVersion": "1.4.28",
57 - "_npmUser": {
58 - "name": "rwky",
59 - "email": "admin@rwky.net"
60 - },
61 - "maintainers": [
62 - {
63 - "name": "aaron",
64 - "email": "aaron.heckmann+github@gmail.com"
65 - },
66 - {
67 - "name": "jongleberry",
68 - "email": "me@jongleberry.com"
69 - },
70 - {
71 - "name": "rwky",
72 - "email": "admin@rwky.net"
73 - },
74 - {
75 - "name": "fragphace",
76 - "email": "fragphace@gmail.com"
77 - }
78 - ],
79 - "dist": {
80 - "shasum": "27a261e0bdfee3d373d24b5a27bd249057355068",
81 - "tarball": "http://registry.npmjs.org/gm/-/gm-1.17.0.tgz"
82 - },
83 - "directories": {},
84 - "_resolved": "https://registry.npmjs.org/gm/-/gm-1.17.0.tgz"
85 -}