├── .circleci
└── config.yml
├── .gitignore
├── .jsbeautifyrc
├── .jscsrc
├── .jsdocrc
├── .jshintrc
├── .prettierignore
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── bower.json
├── dist
├── async.js
└── async.min.js
├── gulp
├── .eslintrc
├── .jshintrc
├── config.js
├── tasks
│ ├── gh-pages.js
│ ├── jscs.js
│ ├── jsdoc.js
│ ├── minify.js
│ ├── npm.js
│ ├── release.js
│ └── test.js
├── template
└── util.js
├── gulpfile.js
├── lib
├── async.js
└── async.min.js
├── package-lock.json
├── package.json
├── perf
├── README.md
├── benchmark
│ └── index.js
├── config.js
├── func-comparator
│ └── index.js
└── index.js
└── test
├── collections
├── test.concat.js
├── test.detect.js
├── test.each.js
├── test.every.js
├── test.filter.js
├── test.groupBy.js
├── test.map.js
├── test.mapValues.js
├── test.omit.js
├── test.pick.js
├── test.reduce.js
├── test.reject.js
├── test.some.js
├── test.sortBy.js
└── test.transform.js
├── config.js
├── controlFlow
├── test.angelFall.js
├── test.apply.js
├── test.applyEach.js
├── test.auto.js
├── test.autoInject.js
├── test.cargo.js
├── test.compose.js
├── test.during.js
├── test.forever.js
├── test.iterator.js
├── test.parallel.js
├── test.queue.js
├── test.race.js
├── test.retry.js
├── test.retryable.js
├── test.seq.js
├── test.series.js
├── test.timeout.js
├── test.times.js
├── test.tryEach.js
├── test.until.js
├── test.waterfall.js
└── test.whilst.js
├── mocha.opts
├── other
├── test.alias.js
└── test.other.js
├── util.js
└── utils
├── test.asyncify.js
├── test.constant.js
├── test.createLogger.js
├── test.ensureAsync.js
├── test.memoize.js
├── test.reflect.js
└── test.unmemoize.js
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 |
2 | # Javascript Node CircleCI 2.0 configuration file
3 | #
4 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details
5 | #
6 | version: 2
7 | jobs:
8 | build:
9 | docker:
10 | # specify the version you desire here
11 | - image: circleci/node:10
12 |
13 | working_directory: ~/repo
14 |
15 | steps:
16 | - checkout
17 |
18 | # Download and cache dependencies
19 | - restore_cache:
20 | keys:
21 | - v1-dependencies-{{ checksum "package.json" }}
22 | # fallback to using the latest cache if no exact match is found
23 | - v1-dependencies-
24 |
25 | - run: npm install
26 |
27 | - save_cache:
28 | paths:
29 | - node_modules
30 | key: v1-dependencies-{{ checksum "package.json" }}
31 |
32 | # run tests!
33 | - run:
34 | name: Test
35 | command: npm test
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | coverage
4 | doc
5 | build
6 | compiler.jar
7 |
8 | .idea
9 |
--------------------------------------------------------------------------------
/.jsbeautifyrc:
--------------------------------------------------------------------------------
1 | {
2 | "indent_size": 2,
3 | "indent_char": " ",
4 | "eol": "\n",
5 | "indent_level": 0,
6 | "indent_with_tabs": false,
7 | "preserve_newlines": true,
8 | "max_preserve_newlines": 2,
9 | "jslint_happy": false,
10 | "space_after_anon_function": false,
11 | "brace_style": "collapse",
12 | "keep_array_indentation": true,
13 | "keep_function_indentation": false,
14 | "space_before_conditional": true,
15 | "break_chained_methods": false,
16 | "eval_code": false,
17 | "unescape_strings": false,
18 | "wrap_line_length": 0,
19 | "wrap_attributes": "auto",
20 | "wrap_attributes_indent_size": 2,
21 | "end_with_newline": true
22 | }
23 |
--------------------------------------------------------------------------------
/.jscsrc:
--------------------------------------------------------------------------------
1 | {
2 | "disallowKeywords": ["with"],
3 | "disallowMixedSpacesAndTabs": true,
4 | "disallowMultipleLineStrings": true,
5 | "disallowNewlineBeforeBlockStatements": true,
6 | "disallowSpaceAfterObjectKeys": true,
7 | "disallowSpaceAfterPrefixUnaryOperators": ["!"],
8 | "disallowSpaceBeforeBinaryOperators": [","],
9 | "disallowSpacesInAnonymousFunctionExpression": {
10 | "beforeOpeningRoundBrace": true
11 | },
12 | "disallowSpacesInFunctionDeclaration": {
13 | "beforeOpeningRoundBrace": true
14 | },
15 | "disallowSpacesInNamedFunctionExpression": {
16 | "beforeOpeningRoundBrace": true
17 | },
18 | "disallowSpacesInsideParentheses": true,
19 | "disallowTrailingComma": true,
20 | "disallowTrailingWhitespace": true,
21 | "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
22 | "requireSpacesInFunction": {
23 | "beforeOpeningCurlyBrace": true
24 | },
25 | "validateParameterSeparator": ", ",
26 | "requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
27 | "requireSpaceAfterBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"],
28 | "requireSpaceBeforeBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"],
29 | "disallowImplicitTypeConversion": ["string"],
30 | "disallowMultipleLineBreaks": true,
31 | "disallowKeywordsOnNewLine": ["else"],
32 | "requireLineFeedAtFileEnd": true
33 | }
34 |
--------------------------------------------------------------------------------
/.jsdocrc:
--------------------------------------------------------------------------------
1 | {
2 | "opts": {
3 | "destination": "./doc",
4 | "recurse": true
5 | },
6 | "source": {
7 | "includePattern": ".+\\.js(doc)?$",
8 | "excludePattern": "(coverage/)|(doc/)|(node_modules/)"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "predef": [
4 | "define",
5 | "Symbol"
6 | ],
7 |
8 | "indent": 2,
9 |
10 | "bitwise": false,
11 | "camelcase": false,
12 | "curly": false,
13 | "eqeqeq": true,
14 | "forin": false,
15 | "immed": true,
16 | "latedef": false,
17 | "newcap": false,
18 | "noarg": true,
19 | "noempty": false,
20 | "nonew": false,
21 | "plusplus": false,
22 | "quotmark": false,
23 | "regexp": false,
24 | "undef": true,
25 | "unused": true,
26 | "strict": true,
27 | "trailing": true,
28 | "maxparams": false,
29 | "maxdepth": false,
30 | "maxstatements": false,
31 | "maxcomplexity": false,
32 | "maxlen": false,
33 |
34 | "boss": false,
35 | "debug": false,
36 | "eqnull": true,
37 | "esnext": true,
38 | "evil": true,
39 | "expr": true,
40 | "funcscope": false,
41 | "globalstrict": false,
42 | "lastsemic": false,
43 | "laxbreak": false,
44 | "laxcomma": true,
45 | "loopfunc": false,
46 | "multistr": false,
47 | "onecase": false,
48 | "proto": true,
49 | "regexdash": false,
50 | "scripturl": true,
51 | "smarttabs": false,
52 | "shadow": false,
53 | "sub": false,
54 | "supernew": false,
55 | "validthis": false,
56 |
57 | "browser": true,
58 | "jquery": true,
59 | "node": true,
60 | "worker": true,
61 |
62 | "nomen": false,
63 | "onevar": false,
64 | "white": false,
65 |
66 | "-W018": true,
67 |
68 | "es3":true
69 | }
70 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | dist
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | arch:
2 | - amd64
3 | - ppc64le
4 | language: node_js
5 |
6 | after_success: 'make test-codecov; make clean'
7 |
8 | install: npm install
9 |
10 | node_js:
11 | - 'node'
12 | - '12'
13 | - '10'
14 | - '8'
15 | - '6'
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2014-2018 Suguru Motegi
4 | Based on Async.js, Copyright Caolan McMahon
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | MOCHA=./node_modules/mocha/bin/_mocha
2 | ISTANBUL=./node_modules/.bin/istanbul
3 |
4 | test-cov: clean
5 | $(ISTANBUL) cover $(MOCHA) --report lcovonly -- -R spec ./test/*/*.js
6 |
7 | test-codecov:
8 | cat ./coverage/lcov.info | ./node_modules/codecov.io/bin/codecov.io.js --verbose
9 |
10 | release-test:
11 | DELAY=20 npm test | npm run-script cov:100
12 |
13 | clean:
14 | rm -rf coverage
15 |
16 | minify:
17 | java -jar ../compiler-latest/compiler.jar --js ./lib/async.js --js_output_file ./lib/async.min.js
18 |
19 | cp:
20 | cp ./lib/async.min.js ./dist/async.min.js
21 | cp ./lib/async.js ./dist/async.js
22 |
23 | release: release-test minify cp
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Neo-Async
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Neo-Async is thought to be used as a drop-in replacement for [Async](https://github.com/caolan/async), it almost fully covers its functionality and runs [faster](#benchmark).
18 |
19 | Benchmark is [here](#benchmark)!
20 |
21 | Bluebird's benchmark is [here](https://github.com/suguru03/bluebird/tree/aigle/benchmark)!
22 |
23 | ## Code Coverage
24 | 
25 |
26 | ## Installation
27 |
28 | ### In a browser
29 | ```html
30 |
31 | ```
32 |
33 | ### In an AMD loader
34 | ```js
35 | require(['async'], function(async) {});
36 | ```
37 |
38 | ### Promise and async/await
39 |
40 | I recommend to use [`Aigle`](https://github.com/suguru03/aigle).
41 |
42 | It is optimized for Promise handling and has almost the same functionality as `neo-async`.
43 |
44 | ### Node.js
45 |
46 | #### standard
47 |
48 | ```bash
49 | $ npm install neo-async
50 | ```
51 | ```js
52 | var async = require('neo-async');
53 | ```
54 |
55 | #### replacement
56 | ```bash
57 | $ npm install neo-async
58 | $ ln -s ./node_modules/neo-async ./node_modules/async
59 | ```
60 | ```js
61 | var async = require('async');
62 | ```
63 |
64 | ### Bower
65 |
66 | ```bash
67 | bower install neo-async
68 | ```
69 |
70 | ## Feature
71 |
72 | [JSDoc](http://suguru03.github.io/neo-async/doc/async.html)
73 |
74 | \* not in Async
75 |
76 | ### Collections
77 |
78 | - [`each`](http://suguru03.github.io/neo-async/doc/async.each.html)
79 | - [`eachSeries`](http://suguru03.github.io/neo-async/doc/async.eachSeries.html)
80 | - [`eachLimit`](http://suguru03.github.io/neo-async/doc/async.eachLimit.html)
81 | - [`forEach`](http://suguru03.github.io/neo-async/doc/async.each.html) -> [`each`](http://suguru03.github.io/neo-async/doc/async.each.html)
82 | - [`forEachSeries`](http://suguru03.github.io/neo-async/doc/async.eachSeries.html) -> [`eachSeries`](http://suguru03.github.io/neo-async/doc/async.eachSeries.html)
83 | - [`forEachLimit`](http://suguru03.github.io/neo-async/doc/async.eachLimit.html) -> [`eachLimit`](http://suguru03.github.io/neo-async/doc/async.eachLimit.html)
84 | - [`eachOf`](http://suguru03.github.io/neo-async/doc/async.each.html) -> [`each`](http://suguru03.github.io/neo-async/doc/async.each.html)
85 | - [`eachOfSeries`](http://suguru03.github.io/neo-async/doc/async.eachSeries.html) -> [`eachSeries`](http://suguru03.github.io/neo-async/doc/async.eachSeries.html)
86 | - [`eachOfLimit`](http://suguru03.github.io/neo-async/doc/async.eachLimit.html) -> [`eachLimit`](http://suguru03.github.io/neo-async/doc/async.eachLimit.html)
87 | - [`forEachOf`](http://suguru03.github.io/neo-async/doc/async.each.html) -> [`each`](http://suguru03.github.io/neo-async/doc/async.each.html)
88 | - [`forEachOfSeries`](http://suguru03.github.io/neo-async/doc/async.eachSeries.html) -> [`eachSeries`](http://suguru03.github.io/neo-async/doc/async.eachSeries.html)
89 | - [`eachOfLimit`](http://suguru03.github.io/neo-async/doc/async.eachLimit.html) -> [`forEachLimit`](http://suguru03.github.io/neo-async/doc/async.eachLimit.html)
90 | - [`map`](http://suguru03.github.io/neo-async/doc/async.map.html)
91 | - [`mapSeries`](http://suguru03.github.io/neo-async/doc/async.mapSeries.html)
92 | - [`mapLimit`](http://suguru03.github.io/neo-async/doc/async.mapLimit.html)
93 | - [`mapValues`](http://suguru03.github.io/neo-async/doc/async.mapValues.html)
94 | - [`mapValuesSeries`](http://suguru03.github.io/neo-async/doc/async.mapValuesSeries.html)
95 | - [`mapValuesLimit`](http://suguru03.github.io/neo-async/doc/async.mapValuesLimit.html)
96 | - [`filter`](http://suguru03.github.io/neo-async/doc/async.filter.html)
97 | - [`filterSeries`](http://suguru03.github.io/neo-async/doc/async.filterSeries.html)
98 | - [`filterLimit`](http://suguru03.github.io/neo-async/doc/async.filterLimit.html)
99 | - [`select`](http://suguru03.github.io/neo-async/doc/async.filter.html) -> [`filter`](http://suguru03.github.io/neo-async/doc/async.filter.html)
100 | - [`selectSeries`](http://suguru03.github.io/neo-async/doc/async.filterSeries.html) -> [`filterSeries`](http://suguru03.github.io/neo-async/doc/async.filterSeries.html)
101 | - [`selectLimit`](http://suguru03.github.io/neo-async/doc/async.filterLimit.html) -> [`filterLimit`](http://suguru03.github.io/neo-async/doc/async.filterLimit.html)
102 | - [`reject`](http://suguru03.github.io/neo-async/doc/async.reject.html)
103 | - [`rejectSeries`](http://suguru03.github.io/neo-async/doc/async.rejectSeries.html)
104 | - [`rejectLimit`](http://suguru03.github.io/neo-async/doc/async.rejectLimit.html)
105 | - [`detect`](http://suguru03.github.io/neo-async/doc/async.detect.html)
106 | - [`detectSeries`](http://suguru03.github.io/neo-async/doc/async.detectSeries.html)
107 | - [`detectLimit`](http://suguru03.github.io/neo-async/doc/async.detectLimit.html)
108 | - [`find`](http://suguru03.github.io/neo-async/doc/async.detect.html) -> [`detect`](http://suguru03.github.io/neo-async/doc/async.detect.html)
109 | - [`findSeries`](http://suguru03.github.io/neo-async/doc/async.detectSeries.html) -> [`detectSeries`](http://suguru03.github.io/neo-async/doc/async.detectSeries.html)
110 | - [`findLimit`](http://suguru03.github.io/neo-async/doc/async.detectLimit.html) -> [`detectLimit`](http://suguru03.github.io/neo-async/doc/async.detectLimit.html)
111 | - [`pick`](http://suguru03.github.io/neo-async/doc/async.pick.html) *
112 | - [`pickSeries`](http://suguru03.github.io/neo-async/doc/async.pickSeries.html) *
113 | - [`pickLimit`](http://suguru03.github.io/neo-async/doc/async.pickLimit.html) *
114 | - [`omit`](http://suguru03.github.io/neo-async/doc/async.omit.html) *
115 | - [`omitSeries`](http://suguru03.github.io/neo-async/doc/async.omitSeries.html) *
116 | - [`omitLimit`](http://suguru03.github.io/neo-async/doc/async.omitLimit.html) *
117 | - [`reduce`](http://suguru03.github.io/neo-async/doc/async.reduce.html)
118 | - [`inject`](http://suguru03.github.io/neo-async/doc/async.reduce.html) -> [`reduce`](http://suguru03.github.io/neo-async/doc/async.reduce.html)
119 | - [`foldl`](http://suguru03.github.io/neo-async/doc/async.reduce.html) -> [`reduce`](http://suguru03.github.io/neo-async/doc/async.reduce.html)
120 | - [`reduceRight`](http://suguru03.github.io/neo-async/doc/async.reduceRight.html)
121 | - [`foldr`](http://suguru03.github.io/neo-async/doc/async.reduceRight.html) -> [`reduceRight`](http://suguru03.github.io/neo-async/doc/async.reduceRight.html)
122 | - [`transform`](http://suguru03.github.io/neo-async/doc/async.transform.html)
123 | - [`transformSeries`](http://suguru03.github.io/neo-async/doc/async.transformSeries.html) *
124 | - [`transformLimit`](http://suguru03.github.io/neo-async/doc/async.transformLimit.html) *
125 | - [`sortBy`](http://suguru03.github.io/neo-async/doc/async.sortBy.html)
126 | - [`sortBySeries`](http://suguru03.github.io/neo-async/doc/async.sortBySeries.html) *
127 | - [`sortByLimit`](http://suguru03.github.io/neo-async/doc/async.sortByLimit.html) *
128 | - [`some`](http://suguru03.github.io/neo-async/doc/async.some.html)
129 | - [`someSeries`](http://suguru03.github.io/neo-async/doc/async.someSeries.html)
130 | - [`someLimit`](http://suguru03.github.io/neo-async/doc/async.someLimit.html)
131 | - [`any`](http://suguru03.github.io/neo-async/doc/async.some.html) -> [`some`](http://suguru03.github.io/neo-async/doc/async.some.html)
132 | - [`anySeries`](http://suguru03.github.io/neo-async/doc/async.someSeries.html) -> [`someSeries`](http://suguru03.github.io/neo-async/doc/async.someSeries.html)
133 | - [`anyLimit`](http://suguru03.github.io/neo-async/doc/async.someLimit.html) -> [`someLimit`](http://suguru03.github.io/neo-async/doc/async.someLimit.html)
134 | - [`every`](http://suguru03.github.io/neo-async/doc/async.every.html)
135 | - [`everySeries`](http://suguru03.github.io/neo-async/doc/async.everySeries.html)
136 | - [`everyLimit`](http://suguru03.github.io/neo-async/doc/async.everyLimit.html)
137 | - [`all`](http://suguru03.github.io/neo-async/doc/async.every.html) -> [`every`](http://suguru03.github.io/neo-async/doc/async.every.html)
138 | - [`allSeries`](http://suguru03.github.io/neo-async/doc/async.everySeries.html) -> [`every`](http://suguru03.github.io/neo-async/doc/async.everySeries.html)
139 | - [`allLimit`](http://suguru03.github.io/neo-async/doc/async.everyLimit.html) -> [`every`](http://suguru03.github.io/neo-async/doc/async.everyLimit.html)
140 | - [`concat`](http://suguru03.github.io/neo-async/doc/async.concat.html)
141 | - [`concatSeries`](http://suguru03.github.io/neo-async/doc/async.concatSeries.html)
142 | - [`concatLimit`](http://suguru03.github.io/neo-async/doc/async.concatLimit.html) *
143 |
144 | ### Control Flow
145 |
146 | - [`parallel`](http://suguru03.github.io/neo-async/doc/async.parallel.html)
147 | - [`series`](http://suguru03.github.io/neo-async/doc/async.series.html)
148 | - [`parallelLimit`](http://suguru03.github.io/neo-async/doc/async.parallelLimit.html)
149 | - [`tryEach`](http://suguru03.github.io/neo-async/doc/async.tryEach.html)
150 | - [`waterfall`](http://suguru03.github.io/neo-async/doc/async.waterfall.html)
151 | - [`angelFall`](http://suguru03.github.io/neo-async/doc/async.angelFall.html) *
152 | - [`angelfall`](http://suguru03.github.io/neo-async/doc/async.angelFall.html) -> [`angelFall`](http://suguru03.github.io/neo-async/doc/async.angelFall.html) *
153 | - [`whilst`](#whilst)
154 | - [`doWhilst`](#doWhilst)
155 | - [`until`](#until)
156 | - [`doUntil`](#doUntil)
157 | - [`during`](#during)
158 | - [`doDuring`](#doDuring)
159 | - [`forever`](#forever)
160 | - [`compose`](#compose)
161 | - [`seq`](#seq)
162 | - [`applyEach`](#applyEach)
163 | - [`applyEachSeries`](#applyEachSeries)
164 | - [`queue`](#queue)
165 | - [`priorityQueue`](#priorityQueue)
166 | - [`cargo`](#cargo)
167 | - [`auto`](#auto)
168 | - [`autoInject`](#autoInject)
169 | - [`retry`](#retry)
170 | - [`retryable`](#retryable)
171 | - [`iterator`](#iterator)
172 | - [`times`](http://suguru03.github.io/neo-async/doc/async.times.html)
173 | - [`timesSeries`](http://suguru03.github.io/neo-async/doc/async.timesSeries.html)
174 | - [`timesLimit`](http://suguru03.github.io/neo-async/doc/async.timesLimit.html)
175 | - [`race`](#race)
176 |
177 | ### Utils
178 | - [`apply`](#apply)
179 | - [`setImmediate`](#setImmediate)
180 | - [`nextTick`](#nextTick)
181 | - [`memoize`](#memoize)
182 | - [`unmemoize`](#unmemoize)
183 | - [`ensureAsync`](#ensureAsync)
184 | - [`constant`](#constant)
185 | - [`asyncify`](#asyncify)
186 | - [`wrapSync`](#asyncify) -> [`asyncify`](#asyncify)
187 | - [`log`](#log)
188 | - [`dir`](#dir)
189 | - [`timeout`](http://suguru03.github.io/neo-async/doc/async.timeout.html)
190 | - [`reflect`](#reflect)
191 | - [`reflectAll`](#reflectAll)
192 | - [`createLogger`](#createLogger)
193 |
194 | ## Mode
195 | - [`safe`](#safe) *
196 | - [`fast`](#fast) *
197 |
198 | ## Benchmark
199 |
200 | [Benchmark: Async vs Neo-Async](http://suguru03.hatenablog.com/entry/2016/06/10/135559)
201 |
202 | ### How to check
203 |
204 | ```bash
205 | $ node perf
206 | ```
207 |
208 | ### Environment
209 |
210 | * Darwin 17.3.0 x64
211 | * Node.js v8.9.4
212 | * async v2.6.0
213 | * neo-async v2.5.0
214 | * benchmark v2.1.4
215 |
216 | ### Result
217 |
218 | The value is the ratio (Neo-Async/Async) of the average speed.
219 |
220 | #### Collections
221 | |function|benchmark|
222 | |---|--:|
223 | |each/forEach|2.43|
224 | |eachSeries/forEachSeries|1.75|
225 | |eachLimit/forEachLimit|1.68|
226 | |eachOf|3.29|
227 | |eachOfSeries|1.50|
228 | |eachOfLimit|1.59|
229 | |map|3.95|
230 | |mapSeries|1.81|
231 | |mapLimit|1.27|
232 | |mapValues|2.73|
233 | |mapValuesSeries|1.59|
234 | |mapValuesLimit|1.23|
235 | |filter|3.00|
236 | |filterSeries|1.74|
237 | |filterLimit|1.17|
238 | |reject|4.59|
239 | |rejectSeries|2.31|
240 | |rejectLimit|1.58|
241 | |detect|4.30|
242 | |detectSeries|1.86|
243 | |detectLimit|1.32|
244 | |reduce|1.82|
245 | |transform|2.46|
246 | |sortBy|4.08|
247 | |some|2.19|
248 | |someSeries|1.83|
249 | |someLimit|1.32|
250 | |every|2.09|
251 | |everySeries|1.84|
252 | |everyLimit|1.35|
253 | |concat|3.79|
254 | |concatSeries|4.45|
255 |
256 | #### Control Flow
257 | |funciton|benchmark|
258 | |---|--:|
259 | |parallel|2.93|
260 | |series|1.96|
261 | |waterfall|1.29|
262 | |whilst|1.00|
263 | |doWhilst|1.12|
264 | |until|1.12|
265 | |doUntil|1.12|
266 | |during|1.18|
267 | |doDuring|2.42|
268 | |times|4.25|
269 | |auto|1.97|
270 |
271 |
272 | ## License
273 | [](https://app.fossa.io/projects/git%2Bgithub.com%2Fsuguru03%2Fneo-async?ref=badge_large)
274 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "neo-async",
3 | "main": "lib/async.js",
4 | "version": "2.6.2",
5 | "homepage": "https://github.com/suguru03/neo-async",
6 | "authors": [
7 | "Suguru Motegi"
8 | ],
9 | "description": "Neo-Async is thought to be used as a drop-in replacement for Async, it almost fully covers its functionality and runs faster ",
10 | "moduleType": [
11 | "amd",
12 | "globals",
13 | "node"
14 | ],
15 | "keywords": [
16 | "async",
17 | "util"
18 | ],
19 | "license": "MIT",
20 | "ignore": [
21 | "**/.*",
22 | "node_modules",
23 | "bower_components",
24 | "test",
25 | "tests"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/gulp/.eslintrc:
--------------------------------------------------------------------------------
1 | env:
2 | node: true
3 | mocha: true
4 |
5 | parserOptions:
6 | ecmaVersion: 8
7 |
8 | extends: 'eslint:recommended'
9 |
10 | rules:
11 | # Possible Errors
12 | no-console: "off"
13 | no-empty: "off"
14 |
15 | # Best Practices
16 | curly: "error"
17 | dot-notation: "error"
18 | eqeqeq: "error"
19 | no-return-assign: "error"
20 | no-proto: "error"
21 | no-case-declarations: "off"
22 |
23 | # Strict Mode
24 | strict: ["error", "global"]
25 |
26 | # Variables
27 |
28 | # Stylistic Issues
29 | camelcase: "error"
30 | comma-dangle: ["error", "never"]
31 | comma-spacing: "error"
32 | indent: ["error", 2]
33 | key-spacing: "error"
34 | linebreak-style: ["error", "unix"]
35 | new-cap: "error"
36 | quotes: ["error", "single"]
37 | semi: ["error", "always"]
38 | space-unary-ops: "error"
39 |
40 | # ECMAScript 6
41 | no-var: "error"
42 |
43 | # Node.js
44 | callback-return: "error"
45 |
--------------------------------------------------------------------------------
/gulp/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": ["define", "Symbol"],
3 |
4 | "indent": 2,
5 |
6 | "bitwise": false,
7 | "camelcase": false,
8 | "curly": false,
9 | "eqeqeq": true,
10 | "forin": false,
11 | "immed": true,
12 | "latedef": false,
13 | "newcap": false,
14 | "noarg": true,
15 | "noempty": false,
16 | "nonew": false,
17 | "plusplus": false,
18 | "quotmark": false,
19 | "regexp": false,
20 | "undef": true,
21 | "unused": true,
22 | "strict": true,
23 | "trailing": true,
24 | "maxparams": false,
25 | "maxdepth": false,
26 | "maxstatements": false,
27 | "maxcomplexity": false,
28 | "maxlen": false,
29 |
30 | "boss": false,
31 | "debug": false,
32 | "eqnull": true,
33 | "evil": true,
34 | "expr": false,
35 | "funcscope": false,
36 | "globalstrict": false,
37 | "lastsemic": false,
38 | "laxbreak": false,
39 | "laxcomma": true,
40 | "loopfunc": false,
41 | "multistr": false,
42 | "onecase": false,
43 | "proto": true,
44 | "regexdash": false,
45 | "scripturl": true,
46 | "smarttabs": false,
47 | "shadow": false,
48 | "sub": false,
49 | "supernew": false,
50 | "validthis": false,
51 |
52 | "browser": true,
53 | "jquery": true,
54 | "node": true,
55 | "worker": true,
56 |
57 | "nomen": false,
58 | "onevar": false,
59 | "white": false,
60 |
61 | "-W018": true,
62 |
63 | "esversion": 6
64 | }
65 |
--------------------------------------------------------------------------------
/gulp/config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | jscs: {
5 | dirnames: ['./lib/async.js', './perf/**', './test/**/*.js', './gulp/**'],
6 | },
7 | jsbeautifier: {
8 | dirnames: ['./lib/async.js', './perf/**', './test/**/*.js', './gulp/**'],
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/gulp/tasks/gh-pages.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const path = require('path');
5 |
6 | const gulp = require('gulp');
7 | const git = require('gulp-git');
8 |
9 | const async = require('../../');
10 | const jsdoc = require('./jsdoc');
11 |
12 | gulp.task('gh-pages', (done) => {
13 | const filepath = path.resolve(__dirname, '../..', 'lib/async.js');
14 | const options = {
15 | encoding: 'utf8',
16 | };
17 | const asyncFile = fs.readFileSync(filepath, options);
18 | async.angelFall(
19 | [
20 | async.apply(git.fetch, 'origin', ''),
21 |
22 | async.apply(git.checkout, 'gh-pages'),
23 |
24 | async.apply(fs.writeFile, filepath, asyncFile, {
25 | encoding: 'utf8',
26 | }),
27 |
28 | async.apply(jsdoc.create),
29 |
30 | async.apply(git.status, {
31 | args: '-s ./doc',
32 | }),
33 |
34 | (result, next) => {
35 | if (!result) {
36 | console.log('[skip commit]');
37 | return checkoutMaster(done);
38 | }
39 | git.exec(
40 | {
41 | args: 'add ./doc ./lib/async.js',
42 | },
43 | next
44 | );
45 | },
46 |
47 | async.apply(git.exec, {
48 | args: `commit -m "docs(jsdoc): update jsdoc [v${async.VERSION}] [ci skip]"`,
49 | }),
50 |
51 | checkoutMaster,
52 | ],
53 | done
54 | );
55 |
56 | function checkoutMaster(next) {
57 | git.checkout('master', next);
58 | }
59 | });
60 |
--------------------------------------------------------------------------------
/gulp/tasks/jscs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const gulp = require('gulp');
4 | const jscs = require('gulp-jscs');
5 |
6 | const config = require('../config');
7 |
8 | gulp.task('jscs', () => {
9 | const { dirnames } = config.jscs;
10 | return gulp.src(dirnames).pipe(jscs('.jscsrc'));
11 | });
12 |
--------------------------------------------------------------------------------
/gulp/tasks/jsdoc.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const exec = require('child_process').exec;
4 | const fs = require('fs');
5 | const path = require('path');
6 |
7 | const gulp = require('gulp');
8 |
9 | const config = JSON.parse(
10 | fs.readFileSync(path.resolve(__dirname, '../..', '.jsdocrc'), {
11 | encoding: 'utf8',
12 | })
13 | );
14 |
15 | function createJSDoc(done) {
16 | const dirpath = path.resolve(__dirname, '../..', config.opts.destination);
17 | exec(`rm -rf ${dirpath}`);
18 | exec('$(npm bin)/jsdoc -c .jsdocrc ./lib/async.js', done);
19 | }
20 |
21 | gulp.task('jsdoc', createJSDoc);
22 |
23 | exports.create = createJSDoc;
24 |
--------------------------------------------------------------------------------
/gulp/tasks/minify.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const qs = require('querystring');
5 | const path = require('path');
6 | const http = require('http');
7 | const { exec } = require('child_process');
8 |
9 | const gulp = require('gulp');
10 |
11 | const filepath = path.resolve(__dirname, '../..', 'lib', 'async.js');
12 | const target = path.resolve(__dirname, '../..', 'lib', 'async.min.js');
13 |
14 | gulp.task('minify:local', (done) => {
15 | const compilerPath = path.resolve(__dirname, '..', 'compiler.jar');
16 | const command = `java -jar ${compilerPath} --js ${filepath} --js_output_file ${target}`;
17 | exec(command, done);
18 | });
19 |
20 | gulp.task('minify', (done) => {
21 | const file = fs.readFileSync(filepath, 'utf8');
22 | const body = qs.stringify({
23 | js_code: file,
24 | compilation_level: 'SIMPLE_OPTIMIZATIONS',
25 | // compilation_level: 'ADVANCED_OPTIMIZATIONS',
26 | output_format: 'text',
27 | output_info: 'compiled_code',
28 | });
29 | const opts = {
30 | hostname: 'closure-compiler.appspot.com',
31 | port: 80,
32 | path: '/compile',
33 | method: 'POST',
34 | headers: {
35 | 'Content-Type': 'application/x-www-form-urlencoded',
36 | Content_length: Buffer.byteLength(file),
37 | },
38 | };
39 | let data = '';
40 | const req = http
41 | .request(opts, (res) => {
42 | res
43 | .setEncoding('utf8')
44 | .on('data', (res) => {
45 | data += res;
46 | })
47 | .on('error', done)
48 | .on('end', () => {
49 | fs.writeFile(target, data, 'utf8', done);
50 | });
51 | })
52 | .on('error', done);
53 | req.write(body);
54 | req.end();
55 | });
56 |
--------------------------------------------------------------------------------
/gulp/tasks/npm.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 |
5 | const _ = require('lodash');
6 | const gulp = require('gulp');
7 | const fs = require('fs-extra');
8 | const argv = require('minimist')(process.argv.slice(2));
9 |
10 | const { exec } = require('../util');
11 | const async = require('../../lib/async');
12 |
13 | gulp.task('npm:publish', publish);
14 |
15 | async function publish() {
16 | const { otp } = argv;
17 | if (!otp) {
18 | throw new Error('Invalid otp');
19 | }
20 | const rootpath = path.resolve(__dirname, '../..');
21 | const buildpath = path.resolve(rootpath, 'build');
22 |
23 | await exec(`rm -rf ${buildpath}`);
24 |
25 | // make dir
26 | !fs.existsSync(buildpath) && fs.mkdirSync(buildpath);
27 |
28 | // copy lib
29 | fs.copySync(path.resolve(rootpath, 'lib', 'async.js'), path.resolve(buildpath, 'async.js'));
30 | // copy the minified file
31 | fs.copySync(
32 | path.resolve(rootpath, 'dist', 'async.min.js'),
33 | path.resolve(buildpath, 'async.min.js')
34 | );
35 |
36 | // copy package.json
37 | const json = _.omit(require('../../package'), ['files', 'scripts', 'private']);
38 | json.main = 'async.js';
39 | json.browser = 'async.min.js';
40 | fs.writeFileSync(path.resolve(buildpath, 'package.json'), JSON.stringify(json, null, 2), 'utf8');
41 |
42 | // copy README
43 | fs.copySync(path.resolve(rootpath, 'README.md'), path.resolve(buildpath, 'README.md'));
44 |
45 | // copy LICENSE
46 | fs.copySync(path.resolve(rootpath, 'LICENSE'), path.resolve(buildpath, 'LICENSE'));
47 |
48 | // create all function files
49 | const template = fs.readFileSync(path.resolve(__dirname, '../template'), 'utf8');
50 | _.forOwn(async, (func, key) => {
51 | if (!_.isFunction(func)) {
52 | return;
53 | }
54 | const file = template.replace('', key);
55 | fs.writeFileSync(path.resolve(buildpath, `${key}.js`), file, 'utf8');
56 | });
57 |
58 | await exec(`cd ${buildpath} && npm publish --otp=${otp}`);
59 | }
60 |
--------------------------------------------------------------------------------
/gulp/tasks/release.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const path = require('path');
5 |
6 | const _ = require('lodash');
7 | const gulp = require('gulp');
8 | const git = require('gulp-git');
9 | const bump = require('gulp-bump');
10 | const tagVersion = require('gulp-tag-version');
11 |
12 | const basepath = path.resolve(__dirname, '../../');
13 | const packagepath = path.resolve(basepath, 'package.json');
14 | const bowerpath = path.resolve(basepath, 'bower.json');
15 | const types = ['patch', 'prepatch', 'minor', 'preminor', 'major', 'premajor'];
16 | const { version: prevVersion } = require(packagepath);
17 |
18 | gulp.task('release:async', async () => {
19 | delete require.cache[packagepath];
20 | const { version } = require(packagepath);
21 | const asyncpath = path.resolve(basepath, 'lib', 'async.js');
22 | const file = fs.readFileSync(asyncpath, 'utf8');
23 | fs.writeFileSync(asyncpath, file.replace(new RegExp(prevVersion, 'g'), version), 'utf8');
24 | });
25 |
26 | gulp.task('release:tag', () => {
27 | return gulp.src(packagepath).pipe(tagVersion());
28 | });
29 |
30 | gulp.task('release:dist', async () => {
31 | _.forEach(['async.js', 'async.min.js'], (file) => {
32 | const filepath = path.resolve(basepath, 'lib', file);
33 | const distpath = path.resolve(basepath, 'dist', file);
34 | fs.createReadStream(filepath).pipe(fs.createWriteStream(distpath));
35 | });
36 | });
37 |
38 | gulp.task('release:commit', () => {
39 | delete require.cache[packagepath];
40 | const { version } = require(packagepath);
41 | return gulp.src(['./dist/*', './lib/*', packagepath, bowerpath]).pipe(git.commit(version));
42 | });
43 |
44 | function updatePackageVersion(type) {
45 | return () => {
46 | return gulp.src([packagepath, bowerpath]).pipe(bump({ type })).pipe(gulp.dest('./'));
47 | };
48 | }
49 |
50 | _.forEach(types, (type) => {
51 | gulp.task(`release:package:${type}`, updatePackageVersion(type));
52 | gulp.task(
53 | `release:${type}`,
54 | gulp.series(
55 | `release:package:${type}`,
56 | 'release:async',
57 | 'minify:local',
58 | 'release:dist',
59 | 'release:commit',
60 | 'release:tag',
61 | 'gh-pages'
62 | )
63 | );
64 | });
65 |
--------------------------------------------------------------------------------
/gulp/tasks/test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const path = require('path');
5 |
6 | const _ = require('lodash');
7 | const gulp = require('gulp');
8 | const exit = require('gulp-exit');
9 | const mocha = require('gulp-mocha');
10 | const gutil = require('gulp-util');
11 | const executor = require('mocha-parallel-executor');
12 |
13 | const config = require('../../test/config');
14 |
15 | function test() {
16 | const filename = gutil.env.file || '*';
17 | const delay = gulp.env.delay;
18 | if (delay) {
19 | config.delay = delay;
20 | }
21 | gulp
22 | .src([`./test/**/test.${filename}*`])
23 | .pipe(
24 | mocha({
25 | reporter: 'spec',
26 | report: 'lcovonly',
27 | timeout: 2000,
28 | })
29 | )
30 | .pipe(exit());
31 | }
32 |
33 | function exec(name, func) {
34 | const filepath = path.resolve(__dirname, '../..', 'lib', name);
35 | const filename = gutil.env.file;
36 | let files;
37 | if (filename) {
38 | files = _.transform(['collections', 'controlFlow', 'other', 'utils'], (result, dir) => {
39 | const p = path.resolve(__dirname, '../../', 'test', dir, `test.${filename}.js`);
40 | if (fs.existsSync(p)) {
41 | result.push(p);
42 | }
43 | });
44 | }
45 | global.async = require(filepath);
46 | global.async_path = filepath;
47 | func({ files: files });
48 | }
49 |
50 | gulp.task('test', () => {
51 | exec('async.js', test);
52 | });
53 |
54 | gulp.task('test:min', () => {
55 | exec('async.min.js', test);
56 | });
57 |
58 | gulp.task('test:fast', () => {
59 | exec('async.js', executor);
60 | });
61 |
62 | gulp.task('test:fast:min', () => {
63 | exec('async.min.js', executor);
64 | });
65 |
--------------------------------------------------------------------------------
/gulp/template:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = require('./async').;
4 |
--------------------------------------------------------------------------------
/gulp/util.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const cp = require('child_process');
4 |
5 | const _ = require('lodash');
6 | const Aigle = require('aigle');
7 |
8 | module.exports = { exec, spawn };
9 |
10 | function exec(command, args) {
11 | command = !args ? command : _.reduce(args, (str, arg) => `${str} ${arg}`, command);
12 | return execute(cp.exec, command);
13 | }
14 |
15 | function spawn(name, args) {
16 | return execute(cp.spawn, name, args);
17 | }
18 |
19 | function execute(func, command, args) {
20 | return new Aigle((resolve, reject) => {
21 | let result = '';
22 | const task = func(command, args);
23 | task.on('close', (err) => (err ? reject(err) : resolve(result)));
24 | task.on('error', reject);
25 | task.stdout.on('data', (data) => (result += `${data}`));
26 | });
27 | }
28 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('./test/config');
4 |
5 | var requireDir = require('require-dir');
6 |
7 | requireDir('./gulp/tasks', { recurse: true });
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "neo-async",
3 | "version": "2.6.2",
4 | "description": "Neo-Async is a drop-in replacement for Async, it almost fully covers its functionality and runs faster ",
5 | "main": "lib/async.js",
6 | "scripts": {
7 | "test": "istanbul cover ./node_modules/.bin/_mocha --report lcovonly -- -R spec ./test --recursive",
8 | "clean": "rm -rf coverage",
9 | "cov:100": "grep Lines | perl -nle 'my ($l, $c, $p, @d) = split(/[\\s%]+/); exit(($p == 100) == 0)'"
10 | },
11 | "license": "MIT",
12 | "keywords": [
13 | "async",
14 | "util"
15 | ],
16 | "private": true,
17 | "repository": {
18 | "type": "git",
19 | "url": "git@github.com:suguru03/neo-async.git"
20 | },
21 | "homepage": "https://github.com/suguru03/neo-async",
22 | "files": [
23 | "LICENSE",
24 | "index.js",
25 | "lib/async.js",
26 | "lib/async.min.js",
27 | "dist/async.js",
28 | "dist/async.min.js"
29 | ],
30 | "dependencies": {},
31 | "devDependencies": {
32 | "aigle": "^1.14.0",
33 | "async": "^2.6.0",
34 | "benchmark": "^2.1.1",
35 | "bluebird": "^3.5.1",
36 | "codecov.io": "^0.1.6",
37 | "fs-extra": "^4.0.2",
38 | "func-comparator": "^0.7.2",
39 | "gulp": "^4.0.2",
40 | "gulp-bump": "^2.8.0",
41 | "gulp-exit": "0.0.2",
42 | "gulp-git": "^2.4.2",
43 | "gulp-jscs": "^4.0.0",
44 | "gulp-mocha": "^4.2.0",
45 | "gulp-tag-version": "^1.3.0",
46 | "gulp-util": "^3.0.7",
47 | "husky": "^4.2.5",
48 | "istanbul": "^0.4.3",
49 | "jsdoc": "^3.5.5",
50 | "jshint": "^2.9.5",
51 | "lint-staged": "^10.2.11",
52 | "lodash": "^4.17.19",
53 | "minimist": "^1.2.3",
54 | "mocha": "^3.5.3",
55 | "mocha-parallel-executor": "^0.3.0",
56 | "mocha.parallel": "^0.15.3",
57 | "prettier": "^2.0.5"
58 | },
59 | "husky": {
60 | "hooks": {
61 | "pre-commit": "lint-staged"
62 | }
63 | },
64 | "lint-staged": {
65 | "*.{js,ts}": [
66 | "prettier --write"
67 | ]
68 | },
69 | "prettier": {
70 | "printWidth": 100,
71 | "singleQuote": true
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/perf/README.md:
--------------------------------------------------------------------------------
1 | # benchmark
2 |
3 | The benchmark tool is using `benchmark.js` and `func-comparator`.
4 |
5 | ## How to execute
6 |
7 | ```bash
8 | // execute all cases
9 | $ node ./
10 |
11 | // specify benchmark tool
12 | $ node ./ -b benchmark // ['benchmark', 'func-comparator']
13 | $ node ./ -b bench
14 | $ node ./ --benchmark func
15 |
16 | // specify function name
17 | $ node ./ --target each // all `each` tasks
18 | $ node ./ --target each:array // only `each:array` task
19 |
20 | // specify times (only func-comparator)
21 | $ node ./ -t 10
22 | $ node ./ --times 10
23 | ```
24 |
25 | ## Sample
26 |
27 | ```bash
28 | $ node ./ --target each
29 |
30 | ======================================
31 | [async], v2.0.0-rc.4
32 | [neo_async], v2.0.0_pre
33 | ======================================
34 | [each:array] Comparating...
35 | --------------------------------------
36 | [benchmark] Executing...
37 | [1] "neo_async" 7.30μs[1.00][1.00]
38 | [2] "async" 22.0μs[0.332][3.01]
39 | --------------------------------------
40 | [func-comparator] Executing...
41 | [1] "neo_async" 80.4μs[1.00][1.00]
42 | [2] "async" 185μs[0.435][2.30]
43 | ======================================
44 | [each:object] Comparating...
45 | --------------------------------------
46 | [benchmark] Executing...
47 | [1] "neo_async" 14.6μs[1.00][1.00]
48 | [2] "async" 32.0μs[0.456][2.19]
49 | --------------------------------------
50 | [func-comparator] Executing...
51 | [1] "neo_async" 135μs[1.00][1.00]
52 | [2] "async" 236μs[0.572][1.75]
53 | ======================================
54 | [each:map] Comparating...
55 | --------------------------------------
56 | [benchmark] Executing...
57 | [1] "neo_async" 9.44μs[1.00][1.00]
58 | [2] "async" 31.7μs[0.297][3.36]
59 | --------------------------------------
60 | [func-comparator] Executing...
61 | [1] "neo_async" 86.4μs[1.00][1.00]
62 | [2] "async" 238μs[0.363][2.75]
63 | ```
64 |
--------------------------------------------------------------------------------
/perf/benchmark/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _ = require('lodash');
4 | var Benchmark = require('benchmark');
5 |
6 | module.exports = function(funcs) {
7 |
8 | return function(callback) {
9 | var suite = new Benchmark.Suite();
10 | var total = {};
11 | _.forEach(funcs, function(func, key) {
12 | total[key] = {
13 | count: 0,
14 | time: 0
15 | };
16 | suite.add(key, {
17 | defer: true,
18 | fn: function(deferred) {
19 | var start = process.hrtime();
20 | func(function() {
21 | var diff = process.hrtime(start);
22 | total[key].time += (diff[0] * 1e9 + diff[1]) / 1000;
23 | total[key].count++;
24 | deferred.resolve();
25 | });
26 | }
27 | });
28 | });
29 |
30 | suite
31 | .on('complete', function() {
32 | var result = _.chain(this)
33 | .map(function(data) {
34 | var name = data.name;
35 | var time = total[name];
36 | return {
37 | name: name,
38 | mean: time.time / time.count
39 | };
40 | })
41 | .sortBy('mean')
42 | .value();
43 | callback(null, result);
44 | })
45 | .run({
46 | async: true
47 | });
48 | };
49 | };
50 |
--------------------------------------------------------------------------------
/perf/func-comparator/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _ = require('lodash');
4 | var Comparator = require('func-comparator').Comparator;
5 |
6 | module.exports = function(funcs, times) {
7 |
8 | return function(callback) {
9 | new Comparator()
10 | .set(funcs)
11 | .async()
12 | .times(times)
13 | .start()
14 | .result(function(err, res) {
15 | if (err) {
16 | return callback(err);
17 | }
18 | var result = _.chain(res)
19 | .map(function(data, name) {
20 | return {
21 | name: name,
22 | mean: data.average
23 | };
24 | })
25 | .sortBy('mean')
26 | .value();
27 |
28 | callback(null, result);
29 | });
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/perf/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var _ = require('lodash');
4 |
5 | var argv = require('minimist')(process.argv.slice(2));
6 |
7 | var benchmark = argv.b || argv.benchmark; // ['benchmark', 'func-comparator'], -b func-comparator
8 | var count = argv.c || argv.count;
9 | var times = argv.t || argv.times;
10 | var target = argv.target; // -t
11 |
12 | var benchmarks = _.filter([
13 | 'benchmark',
14 | 'func-comparator'
15 | ], function(name) {
16 | return benchmark ? RegExp(benchmark).test(name) : name;
17 | });
18 | benchmarks = _.transform(benchmarks, function(result, name) {
19 | result[name] = require('./' + name);
20 | }, {});
21 |
22 | var async = require('../');
23 | var functions = {
24 | async: require('async'),
25 | neo_async: async
26 | };
27 | functions.async.VERSION = require('async/package.json').version;
28 |
29 | console.log('======================================');
30 | _.forOwn(functions, function(obj, key) {
31 | console.log('[%s], v%s', key, obj.VERSION);
32 | });
33 |
34 | var config = require('./config');
35 | var defaults = config.defaults;
36 | var tasks = _.omit(config, 'defaults');
37 | if (target) {
38 | var reg = new RegExp('^' + target + '$');
39 | tasks = _.pickBy(tasks, function(obj, name) {
40 | return reg.test(name) || reg.test(_.first(name.split(':')));
41 | });
42 | }
43 |
44 | async.eachSeries(tasks, function(task, name, done) {
45 | var avaiable = task.avaiable === undefined ? defaults.avaiable : task.avaiable;
46 | if (!avaiable) {
47 | return done();
48 | }
49 | var _count = count || _.get(task, 'count', defaults.count);
50 | var _times = times || _.get(task, 'times', defaults.times);
51 | var setup = _.get(task, 'setup', _.noop);
52 |
53 | setup(_count);
54 |
55 | console.log('======================================');
56 | console.log('[' + name + '] Comparating... ');
57 |
58 | var func = _.get(task, 'func', defaults.func);
59 | async.eachSeries(benchmarks, function(benchmarker, benchmark, next) {
60 | var funcs = _.mapValues(functions, function(async) {
61 | return function(callback) {
62 | func(async, callback);
63 | };
64 | });
65 | console.log('--------------------------------------');
66 | console.log('[%s] Executing...', benchmark);
67 | benchmarker(funcs, _times)(function(err, res) {
68 | if (err) {
69 | return next(err);
70 | }
71 | _.forEach(res, function(data, index, array) {
72 | var name = data.name;
73 | var mean = data.mean;
74 | var diff = (_.first(array).mean) / mean;
75 | var rate = mean / (_.first(array).mean);
76 | console.log('[%d] "%s" %sμs[%s][%s]', ++index, name, mean.toPrecision(3), diff.toPrecision(3), rate.toPrecision(3));
77 | });
78 | next();
79 | });
80 | }, done);
81 | });
82 |
--------------------------------------------------------------------------------
/test/config.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (typeof Symbol !== 'function') {
4 | global.Symbol = function() {};
5 | global.Symbol.iterator = 'symbol';
6 | }
7 |
8 | module.exports = {
9 | delay: process.env.DELAY || 70
10 | };
11 |
--------------------------------------------------------------------------------
/test/controlFlow/test.angelFall.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 | var domain = require('domain');
6 |
7 | var _ = require('lodash');
8 | var parallel = require('mocha.parallel');
9 |
10 | var async = global.async || require('../../');
11 | var delay = require('../config').delay;
12 | var util = require('../util');
13 |
14 | function createSimpleTasks(numbers) {
15 |
16 | var first = true;
17 | var tasks = _.transform(numbers, function(memo, num, key) {
18 | if (first) {
19 | first = false;
20 | memo[key] = function(done) {
21 | if (this === Math) {
22 | num *= 2;
23 | }
24 | done(null, num);
25 | };
26 | } else {
27 | memo[key] = function(sum, done) {
28 | if (this === Math) {
29 | num *= 2;
30 | }
31 | done(null, sum + num);
32 | };
33 | }
34 | });
35 | return tasks;
36 | }
37 |
38 | parallel('#angelFall', function() {
39 |
40 | it('should execute to waterfall by collection of array', function(done) {
41 |
42 | var numbers = [1, 3, 2, 4];
43 | var tasks = createSimpleTasks(numbers);
44 | async.angelFall(tasks, function(err, res) {
45 | if (err) {
46 | return done(err);
47 | }
48 | assert.strictEqual(res, 10);
49 | done();
50 | });
51 | });
52 |
53 | it('should execute simple tasks', function(done) {
54 |
55 | var numbers = [1, 3, 2, 4, 7, 8, 6, 5];
56 | var tasks = createSimpleTasks(numbers);
57 | async.angelFall(tasks, function(err, result) {
58 | if (err) {
59 | return done(err);
60 | }
61 | assert.strictEqual(result, 36);
62 | done();
63 | });
64 | });
65 |
66 | it('should execute example tasks', function(done) {
67 | var order = [];
68 | var tasks = [
69 | function(next) {
70 | setTimeout(function() {
71 | order.push(1);
72 | next(null, 1);
73 | }, 10);
74 | },
75 | function(arg1, empty, next) {
76 | setTimeout(function() {
77 | order.push(2);
78 | next(null, 1, 2);
79 | }, 30);
80 | },
81 | function(next) {
82 | setTimeout(function() {
83 | order.push(3);
84 | next(null, 3);
85 | }, 20);
86 | },
87 | function(arg1, empty1, empty2, empty3, next) {
88 | setTimeout(function() {
89 | order.push(4);
90 | next(null, 1, 2, 3, 4);
91 | }, 40);
92 | }
93 | ];
94 | async.angelFall(tasks, function(err, arg1, arg2, arg3, arg4) {
95 | if (err) {
96 | return done(err);
97 | }
98 | assert.strictEqual(arg1, 1);
99 | assert.strictEqual(arg2, 2);
100 | assert.strictEqual(arg3, 3);
101 | assert.strictEqual(arg4, 4);
102 | done();
103 | });
104 | });
105 |
106 | it('should execute complex tasks', function(done) {
107 |
108 | var tasks = [
109 | function(next) {
110 | next(null, 1);
111 | },
112 | function(arg1, next) {
113 | next(null, arg1, 2);
114 | },
115 | function(arg1, arg2, empty, next) {
116 | next(null, arg1, arg2, 3);
117 | },
118 | function(arg1, arg2, arg3, empty1, empty2, empty3, empty4, next) {
119 | next(null, arg1, arg2, arg3, 4);
120 | },
121 | function(arg1, next) {
122 | next(null, arg1, 2, 3, 4, 5);
123 | },
124 | function(next) {
125 | next(null, 1, 2, 3, 4, 5, 6, 7, 8);
126 | },
127 | function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, empty, next) {
128 | next(null, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, empty, next);
129 | }
130 | ];
131 | async.angelFall(tasks, function(err, a, b, c, d, e, f, g, h, empty) {
132 | if (err) {
133 | return done(err);
134 | }
135 | assert.strictEqual(a, 1);
136 | assert.strictEqual(b, 2);
137 | assert.strictEqual(c, 3);
138 | assert.strictEqual(d, 4);
139 |
140 | assert.strictEqual(e, 5);
141 | assert.strictEqual(f, 6);
142 | assert.strictEqual(g, 7);
143 | assert.strictEqual(h, 8);
144 |
145 | assert.strictEqual(empty, undefined);
146 |
147 | done();
148 | });
149 | });
150 |
151 | it('should execute even if task does not have an argument', function(done) {
152 |
153 | var order = [];
154 | async.angelFall([
155 | function() {
156 | order.push(1);
157 | return 1;
158 | },
159 | function(next) {
160 | order.push(2);
161 | next();
162 | },
163 | function(arg, next) {
164 | order.push(3);
165 | next();
166 | },
167 | function() {
168 | order.push(4);
169 | return 4;
170 | },
171 | function(arg, next) {
172 | assert.strictEqual(arg, 4);
173 | order.push(5);
174 | next();
175 | }
176 | ], function(err) {
177 | if (err) {
178 | return done(err);
179 | }
180 | assert.deepStrictEqual(order, [1, 2, 3, 4, 5]);
181 | done();
182 | });
183 | });
184 |
185 | it('should throw error', function(done) {
186 |
187 | var numbers = [1, 3, 2, 4];
188 | var tasks = createSimpleTasks(numbers);
189 | var errorTask = function(res, next) {
190 | next('error');
191 | };
192 | tasks.splice(2, 0, errorTask);
193 |
194 | async.angelFall(tasks, function(err) {
195 | assert.ok(err);
196 | done();
197 | });
198 | });
199 |
200 | it('should throw error if callback is called twice', function(done) {
201 |
202 | var errorCallCount = 0;
203 | setTimeout(function() {
204 | assert.strictEqual(errorCallCount, 1);
205 | done();
206 | }, delay);
207 |
208 | domain.create()
209 | .on('error', util.errorChecker)
210 | .on('error', function() {
211 | errorCallCount++;
212 | })
213 | .run(function() {
214 | var array = [
215 | function(next) {
216 | setImmediate(function() {
217 | next(null, 'one', 'two');
218 | });
219 | setImmediate(function() {
220 | next(null, 'one', 'two');
221 | });
222 | },
223 | function(arg1, arg2, next) {
224 | next(null, arg1, arg2, 'three');
225 | },
226 | function(arg1, arg2, arg3, next) {
227 | next(null, 'four');
228 | },
229 | function(arg1, next) {
230 | next();
231 | }
232 | ];
233 | async.angelFall(array);
234 | });
235 | });
236 |
237 | it('should throw error if task is not collection', function(done) {
238 |
239 | async.angelFall(null, function(err) {
240 | assert.strictEqual(err.message, 'First argument to waterfall must be an array of functions');
241 | done();
242 | });
243 | });
244 |
245 | it('should throw error with binding', function(done) {
246 |
247 | var numbers = [1, 3, 2, 4];
248 | var tasks = createSimpleTasks(numbers);
249 | var errorTask = function(res, next) {
250 | next('error');
251 | };
252 | tasks.splice(2, 0, errorTask);
253 |
254 | async.angelFall(tasks, function(err) {
255 | assert.ok(err);
256 | done();
257 | }, Math);
258 | });
259 |
260 | it('should throw error if task which does not have an argument throws error', function(done) {
261 |
262 | var order = [];
263 | async.angelFall([
264 | function() {
265 | order.push(1);
266 | return 1;
267 | },
268 | function(next) {
269 | order.push(2);
270 | next();
271 | },
272 | function(arg, next) {
273 | order.push(3);
274 | next();
275 | },
276 | function() {
277 | order.push(4);
278 | throw new Error('error');
279 | },
280 | function(arg, next) {
281 | order.push(5);
282 | next();
283 | }
284 | ], function(err) {
285 | assert.ok(err);
286 | assert.deepStrictEqual(order, [1, 2, 3, 4]);
287 | done();
288 | });
289 | });
290 |
291 | it('should avoid double callback', function(done) {
292 |
293 | var called = false;
294 | var tasks = _.times(3, function(n) {
295 | return function(callback) {
296 | try {
297 | callback('error' + n);
298 | } catch (exception) {
299 | try {
300 | callback(exception);
301 | } catch(e) {
302 | assert.ok(e);
303 | util.errorChecker(e);
304 | }
305 | done();
306 | }
307 | };
308 | });
309 | async.angelFall(tasks, function(err) {
310 | assert.ok(err);
311 | assert.strictEqual(called, false);
312 | called = true;
313 | async.nothing();
314 | });
315 | });
316 |
317 | it('should return response immediately if array task is empty', function(done) {
318 |
319 | var tasks = [];
320 | async.angelFall(tasks, function(err, res) {
321 | if (err) {
322 | return done(err);
323 | }
324 | assert.strictEqual(res, undefined);
325 | done();
326 | });
327 | });
328 |
329 | });
330 |
--------------------------------------------------------------------------------
/test/controlFlow/test.apply.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var _ = require('lodash');
7 | var parallel = require('mocha.parallel');
8 |
9 | var async = global.async || require('../../');
10 |
11 | parallel('#apply', function() {
12 |
13 | it('should apply arguments', function() {
14 |
15 | var func = function() {
16 | assert.deepStrictEqual(Array.prototype.slice.call(arguments), [1, 2, 3, 4]);
17 | };
18 |
19 | async.apply(func, 1, 2, 3, 4)();
20 | async.apply(func, 1, 2, 3)(4);
21 | async.apply(func, 1, 2)(3, 4);
22 | async.apply(func, 1)(2, 3, 4);
23 |
24 | var fn = async.apply(func);
25 | fn(1, 2, 3, 4);
26 | fn(1, 2, 3, 4);
27 |
28 | assert.strictEqual(
29 | async.apply(function(name) {
30 | return 'hello ' + name;
31 | }, 'world')(),
32 | 'hello world'
33 | );
34 | });
35 |
36 | it('should apply long arguments', function() {
37 |
38 | var func = function(a1, a2, a3, a4, a5, a6, a7, a8) {
39 | assert.strictEqual(a8, 8);
40 | assert.strictEqual(_.sum(arguments), 55);
41 | };
42 | var newFunc = async.apply(func, 1, 2, 3, 4, 5, 6, 7);
43 | assert.strictEqual(func.length, 8);
44 | assert.strictEqual(newFunc.length, 1);
45 | newFunc(8, 9, 10);
46 | });
47 |
48 | it('should execute waterfall with apply', function(done) {
49 |
50 | async.waterfall([
51 | function(next) {
52 | next(null, 1);
53 | },
54 | async.apply(function(arg1, arg2, next) {
55 | assert.strictEqual(arg1, 0);
56 | assert.strictEqual(arg2, 1);
57 | next();
58 | }, 0),
59 | async.apply(function(arg1, arg2, arg3, arg4, next) {
60 | assert.strictEqual(arg1, 'a');
61 | assert.strictEqual(arg2, 'b');
62 | assert.strictEqual(arg3, 'c');
63 | assert.strictEqual(arg4, 'd');
64 | next(null, 1, 2, 3);
65 | }, 'a', 'b', 'c', 'd')
66 | ], function(err, res1, res2, res3) {
67 | if (err) {
68 | return done(err);
69 | }
70 | assert.strictEqual(res1, 1);
71 | assert.strictEqual(res2, 2);
72 | assert.strictEqual(res3, 3);
73 | done();
74 | });
75 | });
76 |
77 | it('should execute angelFall with apply', function(done) {
78 |
79 | async.angelFall([
80 | function(next) {
81 | next(null, 1);
82 | },
83 | async.apply(function(arg1, arg2, arg3, next) {
84 | assert.strictEqual(arg1, 0);
85 | assert.strictEqual(arg2, 1);
86 | assert.strictEqual(arg3, undefined);
87 | next();
88 | }, 0),
89 | async.apply(function(arg1, arg2) {
90 | return arg1 + arg2;
91 | }, 1, 2),
92 | async.apply(function(arg1, arg2, arg3, arg4, arg5, arg6, next) {
93 | assert.strictEqual(arg1, 'a');
94 | assert.strictEqual(arg2, 'b');
95 | assert.strictEqual(arg3, 'c');
96 | assert.strictEqual(arg4, 'd');
97 | assert.strictEqual(arg5, 3);
98 | next(null, 1, 2, 3);
99 | }, 'a', 'b', 'c', 'd')
100 | ], function(err, res1, res2, res3) {
101 | if (err) {
102 | return done(err);
103 | }
104 | assert.strictEqual(res1, 1);
105 | assert.strictEqual(res2, 2);
106 | assert.strictEqual(res3, 3);
107 | done();
108 | });
109 | });
110 |
111 | });
112 |
--------------------------------------------------------------------------------
/test/controlFlow/test.applyEach.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var _ = require('lodash');
7 | var parallel = require('mocha.parallel');
8 |
9 | var async = global.async || require('../../');
10 | var util = require('../util');
11 |
12 | parallel('#applyEach', function() {
13 |
14 | it('should execute in parallel', function(done) {
15 |
16 | var order = [];
17 | var one = function(val, cb) {
18 | assert.equal(val, 5);
19 | setTimeout(function() {
20 | order.push(1);
21 | cb(null, 1);
22 | }, 100);
23 | };
24 | var two = function(val, cb) {
25 | assert.equal(val, 5);
26 | setTimeout(function() {
27 | order.push(2);
28 | cb(null, 2);
29 | }, 50);
30 | };
31 | var three = function(val, cb) {
32 | assert.equal(val, 5);
33 | setTimeout(function() {
34 | order.push(3);
35 | cb(null, 3);
36 | }, 150);
37 | };
38 |
39 | async.applyEach([one, two, three], 5, function(err, res) {
40 | if (err) {
41 | return done(err);
42 | }
43 | assert.deepStrictEqual(order, [2, 1, 3]);
44 | assert.deepStrictEqual(res, [1, 2, 3]);
45 | done();
46 | });
47 |
48 | });
49 |
50 | it('should execute as a partial apprication', function(done) {
51 |
52 | var order = [];
53 | var one = function(val, cb) {
54 | assert.equal(val, 5);
55 | setTimeout(function() {
56 | order.push(1);
57 | cb(null, 1);
58 | }, 100);
59 | };
60 | var two = function(val, cb) {
61 | assert.equal(val, 5);
62 | setTimeout(function() {
63 | order.push(2);
64 | cb(null, 2);
65 | }, 50);
66 | };
67 | var three = function(val, cb) {
68 | assert.equal(val, 5);
69 | setTimeout(function() {
70 | order.push(3);
71 | cb(null, 3);
72 | }, 150);
73 | };
74 |
75 | async.applyEach([one, two, three])(5, function(err, res) {
76 | if (err) {
77 | return done(err);
78 | }
79 | assert.deepStrictEqual(order, [2, 1, 3]);
80 | assert.deepStrictEqual(res, [1, 2, 3]);
81 | done();
82 | });
83 | });
84 |
85 | it('should avoid double callback', function(done) {
86 |
87 | var called = false;
88 | var tasks = _.times(3, function(n) {
89 | return function(val, callback) {
90 | try {
91 | callback(val + n);
92 | } catch(exception) {
93 | try {
94 | callback(exception);
95 | } catch(e) {
96 | assert.ok(e);
97 | util.errorChecker(e);
98 | }
99 | done();
100 | }
101 | };
102 | });
103 | async.applyEach(tasks, 5, function(err) {
104 | assert.ok(err);
105 | assert.strictEqual(called, false);
106 | called = true;
107 | async.nothing();
108 | });
109 | });
110 |
111 | });
112 |
113 | parallel('#applyEachSeries', function() {
114 |
115 | it('should execute in series', function(done) {
116 |
117 | var order = [];
118 | var one = function(val, cb) {
119 | assert.equal(val, 5);
120 | setTimeout(function() {
121 | order.push(1);
122 | cb(null, 1);
123 | }, 100);
124 | };
125 | var two = function(val, cb) {
126 | assert.equal(val, 5);
127 | setTimeout(function() {
128 | order.push(2);
129 | cb(null, 2);
130 | }, 50);
131 | };
132 | var three = function(val, cb) {
133 | assert.equal(val, 5);
134 | setTimeout(function() {
135 | order.push(3);
136 | cb(null, 3);
137 | }, 150);
138 | };
139 |
140 | async.applyEachSeries([one, two, three], 5, function(err, res) {
141 | if (err) {
142 | return done(err);
143 | }
144 | assert.deepStrictEqual(order, [1, 2, 3]);
145 | assert.deepStrictEqual(res, [1, 2, 3]);
146 | done();
147 | });
148 | });
149 |
150 | it('should avoid double callback', function(done) {
151 |
152 | var called = false;
153 | var tasks = _.times(3, function(n) {
154 | return function(val, callback) {
155 | try {
156 | callback(val + n);
157 | } catch(exception) {
158 | try {
159 | callback(exception);
160 | } catch(e) {
161 | assert.ok(e);
162 | util.errorChecker(e);
163 | }
164 | done();
165 | }
166 | };
167 | });
168 | async.applyEachSeries(tasks, 5, function(err) {
169 | assert.ok(err);
170 | assert.strictEqual(called, false);
171 | called = true;
172 | async.nothing();
173 | });
174 | });
175 | });
176 |
--------------------------------------------------------------------------------
/test/controlFlow/test.auto.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 | var domain = require('domain');
6 |
7 | var parallel = require('mocha.parallel');
8 |
9 | var async = global.async || require('../../');
10 | var delay = require('../config').delay;
11 | var util = require('../util');
12 |
13 | parallel('#auto', function() {
14 |
15 | it('should execute in accordance with best order', function(done) {
16 |
17 | var order = [];
18 | var tasks = {
19 | task1: ['task2', function(results, callback) {
20 | setTimeout(function() {
21 | order.push('task1');
22 | callback();
23 | }, 25);
24 | }],
25 | task2: function(callback) {
26 | setTimeout(function() {
27 | order.push('task2');
28 | callback();
29 | }, 50);
30 | },
31 | task3: ['task2', function(results, callback) {
32 | order.push('task3');
33 | callback();
34 | }],
35 | task4: ['task1', 'task2', function(results, callback) {
36 | order.push('task4');
37 | callback();
38 | }],
39 | task5: ['task2', function(results, callback) {
40 | setTimeout(function() {
41 | order.push('task5');
42 | callback();
43 | }, 0);
44 | }],
45 | task6: ['task2', function(results, callback) {
46 | order.push('task6');
47 | callback();
48 | }]
49 | };
50 |
51 | async.auto(tasks, function(err) {
52 | if (err) {
53 | return done(err);
54 | }
55 | assert.deepStrictEqual(order, [
56 | 'task2',
57 | 'task3',
58 | 'task6',
59 | 'task5',
60 | 'task1',
61 | 'task4'
62 | ]);
63 | done();
64 | });
65 | });
66 |
67 | it('should execute in accordance with best order and get results', function(done) {
68 |
69 | var order = [];
70 |
71 | async.auto({
72 | task1: ['task2', function(results, callback) {
73 | assert.strictEqual(results.task2, 'task2');
74 | setTimeout(function() {
75 | order.push('task1');
76 | callback(null, 'task1a', 'task1b');
77 | }, 25);
78 | }],
79 | task2: function(callback) {
80 | setTimeout(function() {
81 | order.push('task2');
82 | callback(null, 'task2');
83 | });
84 | },
85 | task3: ['task2', function(results, callback) {
86 | assert.strictEqual(results.task2, 'task2');
87 | order.push('task3');
88 | callback();
89 | }],
90 | task4: ['task1', 'task2', function(results, callback) {
91 | assert.deepStrictEqual(results.task1, ['task1a', 'task1b']);
92 | assert.strictEqual(results.task2, 'task2');
93 | order.push('task4');
94 | callback(null, 'task4');
95 | }]
96 | }, function(err, results) {
97 | if (err) {
98 | return done(err);
99 | }
100 | assert.deepStrictEqual(order, ['task2', 'task3', 'task1', 'task4']);
101 | assert.deepStrictEqual(results, {
102 | task1: ['task1a', 'task1b'],
103 | task2: 'task2',
104 | task3: undefined,
105 | task4: 'task4'
106 | });
107 | done();
108 | });
109 | });
110 |
111 | it('should execute even if array task dosen\'t have nay dependencies', function(done) {
112 |
113 | var order = [];
114 | async.auto({
115 | task1: function(callback) {
116 | order.push('task1');
117 | callback(null, 'task1');
118 | },
119 | task2: ['task3', function(task3, callback) {
120 | order.push('task2');
121 | callback(null, 'task2');
122 | }],
123 | task3: [function(callback) {
124 | order.push('task3');
125 | callback(null, 'task3');
126 | }]
127 | }, function(err, results) {
128 | if (err) {
129 | return done(err);
130 | }
131 | assert.deepStrictEqual(order, [
132 | 'task1',
133 | 'task3',
134 | 'task2'
135 | ]);
136 | assert.deepStrictEqual(results, {
137 | task1: 'task1',
138 | task2: 'task2',
139 | task3: 'task3'
140 | });
141 | done();
142 | });
143 | });
144 |
145 | it('should execute even if object is empty', function(done) {
146 |
147 | async.auto({}, done);
148 | });
149 |
150 | it('should execute without callback', function(done) {
151 |
152 | var tasks = {
153 | task1: function(callback) {
154 | callback();
155 | },
156 | task2: ['task1', function(results, callback) {
157 | callback();
158 | }]
159 | };
160 | async.auto(tasks);
161 | setTimeout(done, delay);
162 | });
163 |
164 | it('should execute without callback', function(done) {
165 |
166 | var tasks = {
167 | task1: function(callback) {
168 | callback();
169 | },
170 | task2: ['task1', function(results, callback) {
171 | callback();
172 | }]
173 | };
174 | async.auto(tasks, 1);
175 | setTimeout(done, delay);
176 | });
177 |
178 | it('should throw error and get safe results', function(done) {
179 |
180 | var order = [];
181 |
182 | async.auto({
183 | task1: ['task2', function(results, callback) {
184 | assert.strictEqual(results.task2, 'task2');
185 | setTimeout(function() {
186 | order.push('task1');
187 | callback(null, 'task1a', 'task1b');
188 | }, 25);
189 | }],
190 | task2: function(callback) {
191 | setTimeout(function() {
192 | order.push('task2');
193 | callback(null, 'task2');
194 | });
195 | },
196 | task3: ['task2', function(results, callback) {
197 | assert.strictEqual(results.task2, 'task2');
198 | order.push('task3');
199 | callback('error', 'task3');
200 | }],
201 | task4: ['task1', 'task2', function(results, callback) {
202 | assert.deepStrictEqual(results.task1, ['task1a', 'task1b']);
203 | assert.strictEqual(results.task2, 'task2');
204 | order.push('task4');
205 | callback(null, 'task4');
206 | }]
207 | }, function(err, results) {
208 | assert.ok(err);
209 | assert.deepStrictEqual(order, ['task2', 'task3']);
210 | assert.deepStrictEqual(results, {
211 | task2: 'task2',
212 | task3: 'task3'
213 | });
214 | done();
215 | });
216 | });
217 |
218 | it('should avoid double callback', function(done) {
219 |
220 | var called = false;
221 | var tasks = {
222 | task1: function(callback) {
223 | try {
224 | callback('error');
225 | } catch(exception) {
226 | try {
227 | callback(exception);
228 | } catch(e) {
229 | assert.ok(e);
230 | util.errorChecker(e);
231 | }
232 | done();
233 | }
234 | }
235 | };
236 | async.auto(tasks, function(err) {
237 | assert.ok(err);
238 | assert.strictEqual(called, false);
239 | called = true;
240 | async.nothing();
241 | });
242 | });
243 |
244 | it('should execute in limited by concurrency', function(done) {
245 | var order = [];
246 | var tasks = {
247 | task1: function(callback) {
248 | order.push('task1');
249 | callback();
250 | },
251 | task2: ['task1', function(results, callback) {
252 | setTimeout(function() {
253 | order.push('task2');
254 | callback();
255 | }, delay * 2);
256 | }],
257 | task3: ['task1', function(results, callback) {
258 | setTimeout(function() {
259 | order.push('task3');
260 | callback();
261 | }, delay * 2);
262 | }],
263 | task4: ['task1', function(results, callback) {
264 | setTimeout(function() {
265 | order.push('task4');
266 | callback();
267 | }, delay * 1);
268 | }],
269 | task5: ['task1', function(results, callback) {
270 | setTimeout(function() {
271 | order.push('task5');
272 | callback();
273 | }, delay * 1);
274 | }],
275 | task6: ['task1', function(results, callback) {
276 | setTimeout(function() {
277 | order.push('task6');
278 | callback();
279 | }, delay * 1);
280 | }]
281 | };
282 | async.auto(tasks, 2, function(err) {
283 | if (err) {
284 | return done(err);
285 | }
286 | assert.deepStrictEqual(order, [
287 | 'task1',
288 | 'task2',
289 | 'task3',
290 | 'task4',
291 | 'task5',
292 | 'task6'
293 | ]);
294 | done();
295 | });
296 | });
297 |
298 | it('should throw error if double callback', function(done) {
299 |
300 | domain.create()
301 | .on('error', util.errorChecker)
302 | .on('error', function() {
303 | done();
304 | })
305 | .run(function() {
306 | async.auto({
307 | task1: function(callback) {
308 | setImmediate(function() {
309 | callback();
310 | callback();
311 | });
312 | },
313 | task2: function(callback) {
314 | callback();
315 | }
316 | });
317 | });
318 | });
319 |
320 | it('should stop execution if a synchronous error occur', function(done) {
321 |
322 | async.auto({
323 | task1: function(callback) {
324 | callback('error');
325 | },
326 | task2: function(callback) {
327 | assert.ok(false);
328 | callback();
329 | }
330 | }, 1, function(err) {
331 | assert.strictEqual(err, 'error');
332 | setTimeout(done, delay);
333 | });
334 | });
335 |
336 | it('should avoid unnecessary deferrals', function(done) {
337 |
338 | var sync = true;
339 | async.auto({
340 | task1: function(callback) {
341 | callback(null, 1);
342 | },
343 | task2: ['task1', function(results, callback) {
344 | callback();
345 | }]
346 | }, function(err) {
347 | if (err) {
348 | return done(err);
349 | }
350 | assert.ok(sync);
351 | done();
352 | });
353 | sync = false;
354 | });
355 |
356 | it('auto prevent dead-locks due to inexistant dependencies', function() {
357 |
358 | var err;
359 | try {
360 | async.auto({
361 | task1: ['noexist', function(results, callback) {
362 | callback(null, 'task1');
363 | }]
364 | });
365 | } catch(e) {
366 | err = e;
367 | assert.ok(e);
368 | assert(/^async.auto task `task1` has non-existent dependency/.test(e.message));
369 | }
370 | assert.ok(err);
371 | });
372 |
373 | it('auto prevent dead-locks due to all cyclic dependencies', function() {
374 |
375 | var err;
376 | try {
377 | async.auto({
378 | task1: ['task2', function(results, callback) {
379 | callback(null, 'task1');
380 | }],
381 | task2: ['task1', function(results, callback) {
382 | callback(null, 'task2');
383 | }]
384 | });
385 | } catch(e) {
386 | err = e;
387 | assert.ok(e);
388 | assert.strictEqual(e.message, 'async.auto task has cyclic dependencies');
389 | }
390 | assert.ok(err);
391 | });
392 |
393 | it('auto prevent dead-locks due to some cyclic dependencies', function() {
394 |
395 | var err;
396 | try {
397 | async.auto({
398 | task1: ['task2', function(results, callback) {
399 | callback(null, 'task1');
400 | }],
401 | task2: ['task1', function(results, callback) {
402 | callback(null, 'task2');
403 | }],
404 | task3: function(callback) {
405 | callback(null, 'task3');
406 | },
407 | task4: ['task5', function(results, callback) {
408 | callback(null, 'task4');
409 | }],
410 | task5: ['task4', function(results, callback) {
411 | callback(null, 'task5');
412 | }]
413 | });
414 | } catch(e) {
415 | err = e;
416 | assert.ok(e);
417 | assert.strictEqual(e.message, 'async.auto task has cyclic dependencies');
418 | }
419 | assert.ok(err);
420 | });
421 |
422 | it('should throw an error if tasks have cyclic dependencies', function() {
423 |
424 | var err;
425 | var task = function(name) {
426 | return function(results, callback) {
427 | callback(null, 'task ' + name);
428 | };
429 | };
430 | try {
431 | async.auto({
432 | a: ['c', task('a')],
433 | b: ['a', task('b')],
434 | c: ['b', task('c')]
435 | });
436 | } catch(e) {
437 | err = e;
438 | assert.ok(e);
439 | assert.strictEqual(e.message, 'async.auto task has cyclic dependencies');
440 | }
441 | assert.ok(err);
442 | });
443 |
444 | it('should work even if reserved name is included', function(done) {
445 | // var async = require('async');
446 | var tasks = {
447 | one: function(next) {
448 | next(null, 1);
449 | },
450 | hasOwnProperty: function(next) {
451 | next(null, 2);
452 | }
453 | };
454 | async.auto(tasks, function(err, res) {
455 | if (err) {
456 | return done(err);
457 | }
458 | assert.deepStrictEqual(res, {
459 | one: 1,
460 | hasOwnProperty: 2
461 | });
462 | done();
463 | });
464 | });
465 |
466 | /**
467 | * @see https://github.com/suguru03/neo-async/issues/57
468 | */
469 | it('should work without cyclic dependencies error', function(done) {
470 | var error = new Error('error');
471 | async.auto({
472 | task1: function(callback) {
473 | setTimeout(callback, delay, error);
474 | },
475 | task2: function(callback) {
476 | setTimeout(callback, delay * 2)
477 | },
478 | task3: ['task1', 'task2', function(callback) {
479 | setTimeout(callback, delay * 2)
480 | }]
481 | }, function(err) {
482 | assert.strictEqual(err, error);
483 | setTimeout(done, delay * 3);
484 | });
485 | });
486 | });
487 |
--------------------------------------------------------------------------------
/test/controlFlow/test.autoInject.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var _ = require('lodash');
7 | var parallel = require('mocha.parallel');
8 |
9 | var async = global.async || require('../../');
10 | var delay = require('../config').delay;
11 | var util = require('../util');
12 |
13 | parallel('#autoInject', function() {
14 |
15 | it('should execute by auto injection', function(done) {
16 |
17 | var order = [];
18 | async.autoInject({
19 | task1: function(task2, callback) {
20 | assert.strictEqual(task2, 2);
21 | setTimeout(function() {
22 | order.push('task1');
23 | callback(null, 1);
24 | }, delay);
25 | },
26 | task2: function(callback) {
27 | setTimeout(function() {
28 | order.push('task2');
29 | callback(null, 2);
30 | }, delay * 2);
31 | },
32 | task3: function(task2, callback) {
33 | assert.strictEqual(task2, 2);
34 | order.push('task3');
35 | callback(null, 3);
36 | },
37 | task4: function(task1, task2, callback) {
38 | assert.strictEqual(task1, 1);
39 | assert.strictEqual(task2, 2);
40 | order.push('task4');
41 | callback(null, 4);
42 | },
43 | task5: function(task2, callback) {
44 | assert.strictEqual(task2, 2);
45 | setTimeout(function() {
46 | order.push('task5');
47 | callback(null, 5);
48 | });
49 | },
50 | task6: function(task2, callback) {
51 | assert.strictEqual(task2, 2);
52 | order.push('task6');
53 | callback(null, 6);
54 | }
55 | }, function(err, result) {
56 | if (err) {
57 | return done(err);
58 | }
59 | assert.deepStrictEqual(result, {
60 | task1: 1,
61 | task2: 2,
62 | task3: 3,
63 | task4: 4,
64 | task5: 5,
65 | task6: 6
66 | });
67 | assert.deepStrictEqual(order, [
68 | 'task2',
69 | 'task3',
70 | 'task6',
71 | 'task5',
72 | 'task1',
73 | 'task4'
74 | ]);
75 | done();
76 | });
77 | });
78 |
79 | it('should work with array tasks', function(done) {
80 |
81 | var order = [];
82 | async.autoInject({
83 | task1: [function(callback) {
84 | order.push('task1');
85 | callback(null, 1);
86 | }],
87 | task2: ['task3', function(task3, callback) {
88 | assert.strictEqual(task3, 3);
89 | order.push('task2');
90 | callback(null, 2);
91 | }],
92 | task3: function(callback) {
93 | order.push('task3');
94 | callback(null, 3);
95 | }
96 | }, function(err, result) {
97 | if (err) {
98 | return done(err);
99 | }
100 | assert.deepStrictEqual(result, {
101 | task1: 1,
102 | task2: 2,
103 | task3: 3
104 | });
105 | assert.deepStrictEqual(order, [
106 | 'task1',
107 | 'task3',
108 | 'task2'
109 | ]);
110 | done();
111 | });
112 | });
113 |
114 | it('should execute tasks', function(done) {
115 |
116 | var order = [];
117 | async.autoInject({
118 | task1: function(callback) {
119 | order.push('task1');
120 | callback(null, 1);
121 | },
122 | task2: ['task3', function(task3, callback) {
123 | order.push('task2');
124 | assert.strictEqual(task3, 3);
125 | callback(null, 2);
126 | }],
127 | task2_1: ['task3', function(arg1, callback) {
128 | order.push('task2_1');
129 | assert.strictEqual(arg1, 3);
130 | assert.ok(_.isFunction(callback));
131 | assert.strictEqual(arguments.length, 2);
132 | callback();
133 | }],
134 | task2_2: function(task3, callback) {
135 | order.push('task2_2');
136 | assert.strictEqual(task3, 3);
137 | callback();
138 | },
139 | task2_3: ['task1', 'task3', function(arg1, arg2, callback) {
140 | order.push('task2_3');
141 | assert.strictEqual(arg1, 1);
142 | assert.strictEqual(arg2, 3);
143 | callback();
144 | }],
145 | task2_4: ['task3', function(arg1, callback) {
146 | order.push('task2_4');
147 | assert.strictEqual(arg1, 3);
148 | callback();
149 | }],
150 | task3: function (callback) {
151 | order.push('task3');
152 | callback(null, 3);
153 | }
154 | }, function(err) {
155 | if (err) {
156 | return done(err);
157 | }
158 | assert.deepStrictEqual(order, [
159 | 'task1',
160 | 'task3',
161 | 'task2',
162 | 'task2_1',
163 | 'task2_2',
164 | 'task2_3',
165 | 'task2_4'
166 | ]);
167 | done();
168 | });
169 | });
170 |
171 | it('should execute complex tasks', function(done) {
172 |
173 | var order = [];
174 | async.autoInject({
175 | task1: ['task3', 'task2', 'task5', 'task6', function(arg1, arg2, arg3, arg4, callback) {
176 | order.push('task1');
177 | assert.strictEqual(arg1, 3);
178 | assert.strictEqual(arg2, 2);
179 | assert.strictEqual(arg3, 5);
180 | assert.strictEqual(arg4, 6);
181 | callback(null, 1);
182 | }],
183 | task2: function(task3, callback) {
184 | assert.strictEqual(task3, 3);
185 | order.push('task2');
186 | callback(null, 2);
187 | },
188 | task3: ['task5', function(arg1, callback) {
189 | assert.strictEqual(arg1, 5);
190 | order.push('task3');
191 | callback(null, 3);
192 | }],
193 | task4: function(task1, task2, task7, callback) {
194 | assert.strictEqual(task1, 1);
195 | assert.strictEqual(task2, 2);
196 | assert.strictEqual(task7, 7);
197 | order.push('task4');
198 | callback(null, 4);
199 | },
200 | task5: function(callback) {
201 | setTimeout(function() {
202 | order.push('task5');
203 | callback(null, 5);
204 | }, delay * 2);
205 | },
206 | task6: function(task7, callback) {
207 | assert.strictEqual(task7, 7);
208 | order.push('task6');
209 | callback(null, 6);
210 | },
211 | task7: function(callback) {
212 | setTimeout(function() {
213 | order.push('task7');
214 | callback(null, 7);
215 | }, delay);
216 | }
217 | }, function(err, result) {
218 | if (err) {
219 | return done(err);
220 | }
221 | assert.deepStrictEqual(result, {
222 | task1: 1,
223 | task2: 2,
224 | task3: 3,
225 | task4: 4,
226 | task5: 5,
227 | task6: 6,
228 | task7: 7
229 | });
230 | assert.deepStrictEqual(order, [
231 | 'task7',
232 | 'task6',
233 | 'task5',
234 | 'task3',
235 | 'task2',
236 | 'task1',
237 | 'task4'
238 | ]);
239 | done();
240 | });
241 | });
242 |
243 | it('should throw an error if task argument length is zero', function() {
244 |
245 | var err;
246 | try {
247 | async.autoInject({
248 | task1: function() {
249 | },
250 | task2: function(task1, callback) {
251 | assert(false);
252 | callback();
253 | }
254 | });
255 | } catch(e) {
256 | err = e;
257 | assert.ok(e);
258 | assert.strictEqual(e.message, 'autoInject task functions require explicit parameters.');
259 | }
260 | assert.ok(err);
261 | });
262 |
263 | it('should throw an error if array task length is empty', function() {
264 |
265 | var err;
266 | try {
267 | async.autoInject({
268 | task1: [],
269 | task2: function(task1, callback) {
270 | callback();
271 | }
272 | });
273 | } catch(e) {
274 | err = e;
275 | assert.ok(e);
276 | assert.strictEqual(e.message, 'autoInject task functions require explicit parameters.');
277 | }
278 | assert.ok(err);
279 | });
280 |
281 | var arrowSupport = true;
282 | try {
283 | /* jshint -W054 */
284 | new Function('x => x');
285 | /* jshint +W054 */
286 | } catch (e) {
287 | arrowSupport = false;
288 | }
289 |
290 | if (arrowSupport) {
291 | // Needs to be run on ES6 only
292 |
293 | /* jshint -W061 */
294 | eval("(function() { " +
295 | " it('should work with es6 arrow syntax', function (done) { " +
296 | " async.autoInject({ " +
297 | " task1: (cb) => cb(null, 1), " +
298 | " task2: ( task3 , cb ) => cb(null, 2), " +
299 | " task3: cb => cb(null, 3) " +
300 | " }, (err, results) => { " +
301 | " assert.deepStrictEqual(results, { " +
302 | " task1: 1, " +
303 | " task2: 2, " +
304 | " task3: 3 " +
305 | " }); " +
306 | " done(); " +
307 | " }); " +
308 | " }); " +
309 | "}) "
310 | )();
311 | /* jshint +W061 */
312 | }
313 |
314 | var defaultSupport = true;
315 |
316 | try {
317 | eval('function x(y = 1){ return y }');
318 | }catch (e) {
319 | defaultSupport = false;
320 | }
321 |
322 | if(arrowSupport && defaultSupport) {
323 | // Needs to be run on ES6 only
324 |
325 | /* eslint {no-eval: 0}*/
326 | eval("(function() { " +
327 | " it('should work with es6 obj method syntax', function (done) { " +
328 | " async.autoInject({ " +
329 | " task1 (cb) { cb(null, 1) }, " +
330 | " task2 ( task3 , cb ) { cb(null, 2) }, " +
331 | " task3 (cb) { cb(null, 3) }, " +
332 | " task4 ( task2 , cb ) { cb(null) }, " +
333 | " task5 ( task4 = 4 , cb ) { cb(null, task4 + 1) } " +
334 | " }, (err, results) => { " +
335 | " assert.strictEqual(results.task1, 1); " +
336 | " assert.strictEqual(results.task3, 3); " +
337 | " assert.strictEqual(results.task4, undefined); " +
338 | " assert.strictEqual(results.task5, 5); " +
339 | " done(); " +
340 | " }); " +
341 | " }); " +
342 | "}) "
343 | )();
344 | }
345 |
346 | it('should avoid double callback', function(done) {
347 |
348 | var called = false;
349 | var tasks = {
350 | task1: function(callback) {
351 | try {
352 | callback('error');
353 | } catch(exception) {
354 | try {
355 | callback(exception);
356 | } catch(e) {
357 | assert.ok(e);
358 | util.errorChecker(e);
359 | }
360 | done();
361 | }
362 | }
363 | };
364 | async.autoInject(tasks, function(err) {
365 | assert.ok(err);
366 | assert.strictEqual(called, false);
367 | called = true;
368 | async.nothing();
369 | });
370 | });
371 | });
372 |
--------------------------------------------------------------------------------
/test/controlFlow/test.cargo.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var _ = require('lodash');
7 | var parallel = require('mocha.parallel');
8 |
9 | var async = global.async || require('../../');
10 | var delay = require('../config').delay;
11 | var util = require('../util');
12 |
13 | parallel('#cargo', function() {
14 |
15 | it('should execute in accordance with payload', function(done) {
16 |
17 | var order = [];
18 | var delays = [4 * delay, 4 * delay, 2 * delay];
19 | var iterator = function(tasks, callback) {
20 | setTimeout(function() {
21 | order.push('process ' + tasks.join(' '));
22 | callback('err', 'arg');
23 | }, delays.shift());
24 | };
25 |
26 | var cargo = async.cargo(iterator, 2);
27 |
28 | cargo.push(1, function(err, arg) {
29 | assert.strictEqual(err, 'err');
30 | assert.strictEqual(arg, 'arg');
31 | assert.strictEqual(cargo.length(), 3);
32 | order.push('callback ' + 1);
33 | });
34 | cargo.push(2, function(err, arg) {
35 | assert.strictEqual(err, 'err');
36 | assert.strictEqual(arg, 'arg');
37 | assert.strictEqual(cargo.length(), 3);
38 | order.push('callback ' + 2);
39 | });
40 |
41 | assert.strictEqual(cargo.length(), 2);
42 |
43 | setTimeout(function() {
44 | cargo.push(3, function(err, arg) {
45 | assert.strictEqual(err, 'err');
46 | assert.strictEqual(arg, 'arg');
47 | assert.strictEqual(cargo.length(), 1);
48 | order.push('callback ' + 3);
49 | });
50 | }, 2 * delay);
51 |
52 | setTimeout(function() {
53 | cargo.push(4, function(err, arg) {
54 | assert.strictEqual(err, 'err');
55 | assert.strictEqual(arg, 'arg');
56 | assert.strictEqual(cargo.length(), 1);
57 | order.push('callback ' + 4);
58 | });
59 | assert.strictEqual(cargo.length(), 2);
60 | cargo.push(5, function(err, arg) {
61 | assert.strictEqual(err, 'err');
62 | assert.strictEqual(arg, 'arg');
63 | order.push('callback ' + 5);
64 | assert.strictEqual(cargo.length(), 0);
65 | });
66 | }, 3 * delay);
67 |
68 | setTimeout(function() {
69 | assert.deepStrictEqual(order, [
70 | 'process 1 2', 'callback 1', 'callback 2',
71 | 'process 3 4', 'callback 3', 'callback 4',
72 | 'process 5', 'callback 5'
73 | ]);
74 | assert.strictEqual(cargo.length(), 0);
75 | done();
76 | }, 20 * delay);
77 | });
78 |
79 | it('should execute without callback', function(done) {
80 |
81 | var order = [];
82 | var delays = [
83 | 4 * delay,
84 | 2 * delay,
85 | 6 * delay,
86 | 2 * delay
87 | ];
88 |
89 | var c = async.cargo(function(tasks, callback) {
90 | setTimeout(function() {
91 | order.push('process ' + tasks.join(' '));
92 | callback('error', 'arg');
93 | }, delays.shift());
94 | }, 2);
95 |
96 | c.push(1);
97 | setTimeout(function() {
98 | c.push(2);
99 | }, 3 * delay);
100 | setTimeout(function() {
101 | c.push(3);
102 | c.push(4);
103 | c.push(5);
104 | }, 4.5 * delay);
105 |
106 | setTimeout(function() {
107 | assert.deepStrictEqual(order, [
108 | 'process 1',
109 | 'process 2',
110 | 'process 3 4',
111 | 'process 5'
112 | ]);
113 | done();
114 | }, 20 * delay);
115 |
116 | });
117 |
118 | it('should execute with bulk tasks', function(done) {
119 |
120 | var order = [];
121 | var delays = [3 * delay, delay];
122 |
123 | var c = async.cargo(function(tasks, callback) {
124 | setTimeout(function() {
125 | order.push('process ' + tasks.join(' '));
126 | callback('error', tasks.join(' '));
127 | }, delays.shift());
128 | }, 3);
129 |
130 | c.push([1, 2, 3, 4], function(err, arg) {
131 | assert.strictEqual(err, 'error');
132 | order.push('callback ' + arg);
133 | });
134 |
135 | assert.strictEqual(c.length(), 4);
136 |
137 | setTimeout(function() {
138 | assert.deepStrictEqual(order, [
139 | 'process 1 2 3',
140 | 'callback 1 2 3',
141 | 'callback 1 2 3',
142 | 'callback 1 2 3',
143 | 'process 4',
144 | 'callback 4'
145 | ]);
146 | done();
147 | }, 20 * delay);
148 | });
149 |
150 | it('should execute drain once', function(done) {
151 |
152 | var order = [];
153 | var c = async.cargo(function(tasks, callback) {
154 | order.push(tasks);
155 | callback();
156 | }, 3);
157 |
158 | var drainCounter = 0;
159 | c.drain = function() {
160 | drainCounter++;
161 | };
162 |
163 | var n = 10;
164 | _.times(n, c.push);
165 | assert.strictEqual(c.length(), 10);
166 |
167 | setTimeout(function() {
168 | assert.deepStrictEqual(order, [
169 | [0, 1, 2],
170 | [3, 4, 5],
171 | [6, 7, 8],
172 | [9]
173 | ]);
174 | assert.strictEqual(drainCounter, 1);
175 | done();
176 | }, 120);
177 |
178 | });
179 |
180 | it('should execute drain twice', function(done) {
181 |
182 | var order = [];
183 | var c = async.cargo(function(tasks, callback) {
184 | order.push(tasks);
185 | assert.ok(c.running());
186 | callback();
187 | }, 3);
188 |
189 | var drainCounter = 0;
190 | c.drain = function() {
191 | drainCounter++;
192 | };
193 | var saturated = false;
194 | c.saturated = function() {
195 | saturated = true;
196 | };
197 |
198 | var n = 10;
199 | var loadCargo = _.times.bind(_, n, c.push);
200 | loadCargo();
201 | assert.strictEqual(c.length(), 10);
202 |
203 | var empty = false;
204 | c.empty = function() {
205 | empty = true;
206 | };
207 | setTimeout(loadCargo, 5 * delay);
208 |
209 | setTimeout(function() {
210 | assert.deepStrictEqual(order, [
211 | [0, 1, 2],
212 | [3, 4, 5],
213 | [6, 7, 8],
214 | [9],
215 | [0, 1, 2],
216 | [3, 4, 5],
217 | [6, 7, 8],
218 | [9]
219 | ]);
220 | assert.strictEqual(drainCounter, 2);
221 | assert.ok(saturated);
222 | assert.ok(empty);
223 | done();
224 | }, 10 * delay);
225 |
226 | });
227 |
228 | it('should get workers list', function(done) {
229 |
230 | var order = [];
231 | var workersList = [];
232 | var tasks = [0, 1, 2, 3, 4];
233 | var payload = 3;
234 | var worker = function(tasks, callback) {
235 | order.push(tasks);
236 | workersList.push(_.cloneDeep(c.workersList()));
237 | callback();
238 | };
239 | var c = async.cargo(worker, payload);
240 | c.push(tasks);
241 | c.drain = function() {
242 | assert.deepStrictEqual(order, [
243 | [0, 1, 2],
244 | [3, 4]
245 | ]);
246 | assert.strictEqual(workersList.length, 2);
247 | assert.strictEqual(workersList[0].length, 3);
248 | assert.strictEqual(workersList[1].length, 2);
249 | done();
250 | };
251 | });
252 |
253 | it('should check events', function (done) {
254 |
255 | var calls = [];
256 | var q = async.cargo(function(task, cb) {
257 | // nop
258 | calls.push('process ' + task);
259 | async.setImmediate(cb);
260 | }, 1);
261 | q.concurrency = 3;
262 |
263 | q.saturated = function() {
264 | assert(q.running() === 3, 'cargo should be saturated now');
265 | calls.push('saturated');
266 | };
267 | q.empty = function() {
268 | assert(q.length() === 0, 'cargo should be empty now');
269 | calls.push('empty');
270 | };
271 | q.drain = function() {
272 | assert(
273 | q.length() === 0 && q.running() === 0,
274 | 'cargo should be empty now and no more workers should be running'
275 | );
276 | calls.push('drain');
277 | assert.deepStrictEqual(calls, [
278 | 'process foo',
279 | 'process bar',
280 | 'saturated',
281 | 'process zoo',
282 | 'foo cb',
283 | 'saturated',
284 | 'process poo',
285 | 'bar cb',
286 | 'empty',
287 | 'saturated',
288 | 'process moo',
289 | 'zoo cb',
290 | 'poo cb',
291 | 'moo cb',
292 | 'drain'
293 | ]);
294 | done();
295 | };
296 | q.push('foo', function () {calls.push('foo cb');});
297 | q.push('bar', function () {calls.push('bar cb');});
298 | q.push('zoo', function () {calls.push('zoo cb');});
299 | q.push('poo', function () {calls.push('poo cb');});
300 | q.push('moo', function () {calls.push('moo cb');});
301 | });
302 |
303 | it('should avoid double callback', function(done) {
304 |
305 | var called = false;
306 | var iterator = function(task, callback) {
307 | try {
308 | callback('error');
309 | } catch(exception) {
310 | try {
311 | callback(exception);
312 | } catch(e) {
313 | assert.ok(e);
314 | util.errorChecker(e);
315 | }
316 | done();
317 | }
318 | };
319 | var cargo = async.cargo(iterator);
320 | cargo.push(1, function(err) {
321 | assert.ok(err);
322 | assert.strictEqual(called, false);
323 | called = true;
324 | async.nothing();
325 | });
326 | });
327 |
328 | });
329 |
--------------------------------------------------------------------------------
/test/controlFlow/test.compose.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = global.async || require('../../');
9 |
10 | parallel('#compose', function() {
11 |
12 | it('should execute in order of insertion', function(done) {
13 |
14 | var add2 = function(n, cb) {
15 | assert.strictEqual(n, 3);
16 | setTimeout(function() {
17 | cb(null, n + 2);
18 | }, 50);
19 | };
20 |
21 | var mul3 = function(n, cb) {
22 | assert.strictEqual(n, 5);
23 | setTimeout(function() {
24 | cb(null, n * 3);
25 | }, 15);
26 | };
27 |
28 | var add1 = function(n, cb) {
29 | assert.strictEqual(n, 15);
30 | setTimeout(function() {
31 | cb(null, n + 1);
32 | }, 100);
33 | };
34 |
35 | var add2mul3add1 = async.compose(add1, mul3, add2);
36 |
37 | add2mul3add1(3, function(err, res) {
38 | if (err) {
39 | return done(err);
40 | }
41 | assert.strictEqual(res, 16);
42 | done();
43 | });
44 |
45 | });
46 |
47 | it('should execute in order of insertion with binding', function(done) {
48 |
49 | var pow2 = function(n, cb) {
50 | var self = this;
51 | assert.strictEqual(n, 3);
52 | setTimeout(function() {
53 | cb(null, self.pow(n, 2));
54 | }, 50);
55 | };
56 |
57 | var mul3 = function(n, cb) {
58 | assert.strictEqual(n, 9);
59 | setTimeout(function() {
60 | cb(null, n * 3);
61 | }, 15);
62 | };
63 |
64 | var pow3 = function(n, cb) {
65 | var self = this;
66 | assert.strictEqual(n, 27);
67 | setTimeout(function() {
68 | cb(null, self.pow(n, 3));
69 | }, 100);
70 | };
71 |
72 | var add2mul3add1 = async.compose(pow3, mul3, pow2);
73 |
74 | add2mul3add1.call(Math, 3, function(err, res) {
75 | if (err) {
76 | return done(err);
77 | }
78 | assert.strictEqual(res, 19683);
79 | done();
80 | });
81 |
82 | });
83 |
84 | it('should throw error', function(done) {
85 |
86 | var add2 = function(n, cb) {
87 | assert.strictEqual(n, 3);
88 | setTimeout(function() {
89 | cb(null, n + 2);
90 | }, 50);
91 | };
92 |
93 | var mul3 = function(n, cb) {
94 | assert.strictEqual(n, 5);
95 | setTimeout(function() {
96 | cb(new Error('error'));
97 | }, 15);
98 | };
99 |
100 | var add1 = function(n, cb) {
101 | setTimeout(function() {
102 | cb(null, n + 1);
103 | }, 100);
104 | };
105 |
106 | var add2mul3add1 = async.compose(add1, mul3, add2);
107 |
108 | add2mul3add1(3, function(err) {
109 | assert.ok(err);
110 | done();
111 | });
112 |
113 | });
114 |
115 | it('should execute with binding', function(done) {
116 |
117 | var testContext = {
118 | name: 'foo'
119 | };
120 |
121 | var add2 = function(n, cb) {
122 | assert.strictEqual(this, testContext);
123 | setTimeout(function() {
124 | cb(null, n + 2);
125 | }, 50);
126 | };
127 |
128 | var mul3 = function(n, cb) {
129 | assert.strictEqual(this, testContext);
130 | setTimeout(function() {
131 | cb(null, n * 3);
132 | }, 15);
133 | };
134 |
135 | var add2mul3add1 = async.compose(mul3, add2);
136 |
137 | add2mul3add1.call(testContext, 3, function(err, result) {
138 | if (err) {
139 | return done(err);
140 | }
141 | assert.strictEqual(this, testContext);
142 | assert.strictEqual(result, 15);
143 | done();
144 | });
145 |
146 | });
147 |
148 | });
149 |
--------------------------------------------------------------------------------
/test/controlFlow/test.during.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var _ = require('lodash');
7 | var parallel = require('mocha.parallel');
8 |
9 | var async = global.async || require('../../');
10 |
11 | parallel('#during', function() {
12 |
13 | it('should execute until asynchronous test is false', function(done) {
14 |
15 | var order = [];
16 | var count = 0;
17 | var test = function(callback) {
18 | order.push(['test', count]);
19 | callback(null, count < 5);
20 | };
21 | var iterator = function(callback) {
22 | order.push(['iterator', count]);
23 | count++;
24 | setTimeout(function() {
25 | callback();
26 | }, 10);
27 | };
28 | async.during(test, iterator, function(err) {
29 | if (err) {
30 | return done(err);
31 | }
32 | assert.strictEqual(count, 5);
33 | assert.deepStrictEqual(order, [
34 | ['test', 0],
35 | ['iterator', 0],
36 | ['test', 1],
37 | ['iterator', 1],
38 | ['test', 2],
39 | ['iterator', 2],
40 | ['test', 3],
41 | ['iterator', 3],
42 | ['test', 4],
43 | ['iterator', 4],
44 | ['test', 5]
45 | ]);
46 | done();
47 | });
48 | });
49 |
50 | it('should execute without binding until asynchronous test is false', function(done) {
51 |
52 | var count = 0;
53 | var sum = 0;
54 | var test = function(callback) {
55 | callback(null, count < 5);
56 | };
57 | var iterator = function(callback) {
58 | count++;
59 | sum += this && this.num || 3;
60 | setTimeout(function() {
61 | callback();
62 | }, 10);
63 | };
64 | async.during(test, iterator, function(err) {
65 | if (err) {
66 | return done(err);
67 | }
68 | assert.strictEqual(count, 5);
69 | assert.strictEqual(sum, 15);
70 | done();
71 | }, {
72 | num: 2
73 | });
74 | });
75 |
76 | it('should throw error if error occurs in test', function(done) {
77 |
78 | var count = 0;
79 | var test = function(callback) {
80 | callback(new Error('error'));
81 | };
82 | var iterator = function(callback) {
83 | count++;
84 | callback();
85 | };
86 | async.during(test, iterator, function(err) {
87 | assert.ok(err);
88 | assert.strictEqual(count, 0);
89 | done();
90 | });
91 | });
92 |
93 | it('should throw error if error occurs in iterator', function(done) {
94 |
95 | var count = 0;
96 | var test = function(callback) {
97 | callback(null, count < 5);
98 | };
99 | var iterator = function(callback) {
100 | count++;
101 | callback(new Error('error'));
102 | };
103 | async.during(test, iterator, function(err) {
104 | assert.ok(err);
105 | assert.strictEqual(count, 1);
106 | done();
107 | });
108 | });
109 |
110 | });
111 |
112 | parallel('#doDuring', function() {
113 |
114 | it('should execute until asynchronous test is false', function(done) {
115 |
116 | var order = [];
117 | var count = 0;
118 | var test = function(callback) {
119 | order.push(['test', count]);
120 | callback(null, count < 5);
121 | };
122 | var iterator = function(callback) {
123 | order.push(['iterator', count]);
124 | count++;
125 | setTimeout(function() {
126 | callback();
127 | }, 10);
128 | };
129 | async.doDuring(iterator, test, function(err) {
130 | if (err) {
131 | return done(err);
132 | }
133 | assert.strictEqual(count, 5);
134 | assert.deepStrictEqual(order, [
135 | ['iterator', 0],
136 | ['test', 1],
137 | ['iterator', 1],
138 | ['test', 2],
139 | ['iterator', 2],
140 | ['test', 3],
141 | ['iterator', 3],
142 | ['test', 4],
143 | ['iterator', 4],
144 | ['test', 5]
145 | ]);
146 | done();
147 | });
148 | });
149 |
150 | it('should execute with binding until asynchronous test is false', function(done) {
151 |
152 | var order = [];
153 | var count = 0;
154 | var sum = 0;
155 | var test = function(callback) {
156 | order.push(['test', count]);
157 | callback(null, count < 5);
158 | };
159 | var iterator = function(callback) {
160 | order.push(['iterator', count]);
161 | count++;
162 | sum += this && this.num || 3;
163 | setTimeout(function() {
164 | callback();
165 | }, 10);
166 | };
167 | async.doDuring(iterator, test, function(err) {
168 | if (err) {
169 | return done(err);
170 | }
171 | assert.strictEqual(count, 5);
172 | assert.strictEqual(sum, 15);
173 | assert.deepStrictEqual(order, [
174 | ['iterator', 0],
175 | ['test', 1],
176 | ['iterator', 1],
177 | ['test', 2],
178 | ['iterator', 2],
179 | ['test', 3],
180 | ['iterator', 3],
181 | ['test', 4],
182 | ['iterator', 4],
183 | ['test', 5]
184 | ]);
185 | done();
186 | }, {
187 | num: 2
188 | });
189 | });
190 |
191 | it('should execute with some arguments', function(done) {
192 |
193 | var order = [];
194 | var count = 0;
195 | var test = function() {
196 | order.push(['test', count]);
197 | if (count % 2) {
198 | assert.strictEqual(arguments.length, 2);
199 | } else {
200 | assert.strictEqual(arguments.length, 3);
201 | }
202 | var callback = _.slice(arguments).pop();
203 | callback(null, count < 5);
204 | };
205 | var iterator = function(callback) {
206 | order.push(['iterator', count]);
207 | count++;
208 | setTimeout(function() {
209 | if (count % 2) {
210 | callback(null, 1);
211 | } else {
212 | callback(null, 1, 2);
213 | }
214 | }, 10);
215 | };
216 | async.doDuring(iterator, test, function(err) {
217 | if (err) {
218 | return done(err);
219 | }
220 | assert.deepStrictEqual(order, [
221 | ['iterator', 0],
222 | ['test', 1],
223 | ['iterator', 1],
224 | ['test', 2],
225 | ['iterator', 2],
226 | ['test', 3],
227 | ['iterator', 3],
228 | ['test', 4],
229 | ['iterator', 4],
230 | ['test', 5]
231 | ]);
232 | done();
233 | });
234 | });
235 |
236 | it('should throw error if error occurs in test', function(done) {
237 |
238 | var count = 0;
239 | var test = function(callback) {
240 | callback(new Error('error'));
241 | };
242 | var iterator = function(callback) {
243 | count++;
244 | callback();
245 | };
246 | async.doDuring(iterator, test, function(err) {
247 | assert.ok(err);
248 | assert.strictEqual(count, 1);
249 | done();
250 | });
251 | });
252 |
253 | it('should throw error if error occurs in iterator', function(done) {
254 |
255 | var count = 0;
256 | var test = function(callback) {
257 | callback(null, count < 5);
258 | };
259 | var iterator = function(callback) {
260 | count++;
261 | callback(new Error('error'));
262 | };
263 | async.doDuring(iterator, test, function(err) {
264 | assert.ok(err);
265 | assert.strictEqual(count, 1);
266 | done();
267 | });
268 | });
269 |
270 | });
271 |
--------------------------------------------------------------------------------
/test/controlFlow/test.forever.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 | var domain = require('domain');
6 |
7 | var parallel = require('mocha.parallel');
8 |
9 | var async = global.async || require('../../');
10 |
11 | parallel('#forever', function() {
12 |
13 | it('should execute until error occurs', function(done) {
14 |
15 | var count = 0;
16 | var limit = 5;
17 | var order = [];
18 | var iterator = function(callback) {
19 | order.push(count++);
20 | if (count === limit) {
21 | return callback(new Error('end'));
22 | }
23 | callback();
24 | };
25 |
26 | async.forever(iterator, function(err) {
27 | assert.ok(err);
28 | assert.deepStrictEqual(order, [0, 1, 2, 3, 4]);
29 | done();
30 | });
31 | });
32 |
33 | it('should execute without binding until error occurs', function(done) {
34 |
35 | var count = 0;
36 | var limit = 5;
37 | var order = [];
38 | var result = [];
39 | var iterator = function(callback) {
40 | assert.strictEqual(this, undefined);
41 | result.push(count * count);
42 | order.push(count++);
43 | if (count === limit) {
44 | return callback(new Error('end'));
45 | }
46 | callback();
47 | };
48 |
49 | async.forever(iterator, function(err) {
50 | assert.ok(err);
51 | assert.deepStrictEqual(order, [0, 1, 2, 3, 4]);
52 | assert.deepStrictEqual(result, [0, 1, 4, 9, 16]);
53 | done();
54 | }, Math);
55 | });
56 |
57 | it('should execute on asynchronous', function(done) {
58 |
59 | var sync = true;
60 | var count = 0;
61 | var limit = 5;
62 | var iterator = function(callback) {
63 | if (count++ === limit) {
64 | return callback(new Error('end'));
65 | }
66 | callback();
67 | };
68 | async.forever(iterator, function(err) {
69 | assert.ok(err);
70 | assert.strictEqual(sync, false);
71 | done();
72 | });
73 | sync = false;
74 | });
75 |
76 | it('should throw error', function(done) {
77 |
78 | var count = 0;
79 | var limit = 5;
80 | var order = [];
81 | var iterator = function(callback) {
82 | order.push(count++);
83 | if (count === limit) {
84 | return callback(new Error('end'));
85 | }
86 | callback();
87 | };
88 | domain.create()
89 | .on('error', function(err) {
90 | assert.strictEqual(err.message, 'end');
91 | assert.deepStrictEqual(order, [0, 1, 2, 3, 4]);
92 | done();
93 | })
94 | .run(function() {
95 | async.forever(iterator);
96 | });
97 | });
98 |
99 | });
100 |
--------------------------------------------------------------------------------
/test/controlFlow/test.iterator.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = global.async || require('../../');
9 |
10 | parallel('#iterator', function() {
11 |
12 | it('should execute iterators', function(done) {
13 |
14 | var order = [];
15 | var iterator = async.iterator([
16 | function() {
17 | order.push(1);
18 | },
19 | function(arg1) {
20 | assert.strictEqual(arg1, 'arg1');
21 | order.push(2);
22 | },
23 | function(arg1, arg2) {
24 | assert.strictEqual(arg1, 'arg1');
25 | assert.strictEqual(arg2, 'arg2');
26 | order.push(3);
27 | }
28 | ]);
29 |
30 | iterator();
31 | assert.deepStrictEqual(order, [1]);
32 | var iterator2 = iterator();
33 | assert.deepStrictEqual(order, [1, 1]);
34 | var iterator3 = iterator2('arg1');
35 | assert.deepStrictEqual(order, [1, 1, 2]);
36 | var iterator4 = iterator3('arg1', 'arg2');
37 | assert.deepStrictEqual(order, [1, 1, 2, 3]);
38 | assert.strictEqual(iterator4, null);
39 | done();
40 | });
41 |
42 | it('should execute object iterators', function(done) {
43 |
44 | var order = [];
45 | var iterator = async.iterator({
46 | a: function() {
47 | order.push(1);
48 | },
49 | b: function(arg1) {
50 | assert.strictEqual(arg1, 'arg1');
51 | order.push(2);
52 | },
53 | c: function(arg1, arg2) {
54 | assert.strictEqual(arg1, 'arg1');
55 | assert.strictEqual(arg2, 'arg2');
56 | order.push(3);
57 | }
58 | });
59 |
60 | iterator();
61 | assert.deepStrictEqual(order, [1]);
62 | var iterator2 = iterator();
63 | assert.deepStrictEqual(order, [1, 1]);
64 | var iterator3 = iterator2('arg1');
65 | assert.deepStrictEqual(order, [1, 1, 2]);
66 | var iterator4 = iterator3('arg1', 'arg2');
67 | assert.deepStrictEqual(order, [1, 1, 2, 3]);
68 | assert.strictEqual(iterator4, null);
69 | done();
70 |
71 | });
72 |
73 | it('should get undefined if array is empty', function(done) {
74 |
75 | var iterator = async.iterator([]);
76 | assert.deepStrictEqual(iterator(), null);
77 | assert.deepStrictEqual(iterator.next(), null);
78 | done();
79 | });
80 |
81 | it('should get next iterator', function(done) {
82 |
83 | var order = [];
84 | var iterator = async.iterator([
85 | function() {
86 | order.push(1);
87 | },
88 | function(arg1) {
89 | assert.strictEqual(arg1, 'arg1');
90 | order.push(2);
91 | },
92 | function(arg1, arg2) {
93 | assert.strictEqual(arg1, 'arg1');
94 | assert.strictEqual(arg2, 'arg2');
95 | order.push(3);
96 | }
97 | ]);
98 |
99 | var fn = iterator.next();
100 | var iterator2 = fn('arg1');
101 | assert.deepStrictEqual(order, [2]);
102 | iterator2('arg1', 'arg2');
103 | assert.deepStrictEqual(order, [2, 3]);
104 | assert.deepStrictEqual(iterator2.next(), null);
105 | done();
106 | });
107 |
108 | });
109 |
--------------------------------------------------------------------------------
/test/controlFlow/test.parallel.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 | var domain = require('domain');
6 |
7 | var _ = require('lodash');
8 | var parallel = require('mocha.parallel');
9 |
10 | var async = global.async || require('../../');
11 | var delay = require('../config').delay;
12 | var util = require('../util');
13 |
14 | function createTasks(order, numbers) {
15 |
16 | return _.transform(numbers, function(memo, num, index) {
17 |
18 | memo[index] = function(callback) {
19 | var self = this;
20 | setTimeout(function() {
21 | order.push(num);
22 | if (self && self.round) {
23 | num = self.round(num);
24 | }
25 | callback(null, num * 2);
26 | }, num * delay);
27 | };
28 | });
29 | }
30 |
31 | parallel('#parallel', function() {
32 |
33 | it('should execute in parallel by tasks of array', function(done) {
34 |
35 | var order = [];
36 | var numbers = [1, 3, 2, 4];
37 | var tasks = createTasks(order, numbers);
38 | tasks.push(function(cb) {
39 | setTimeout(function() {
40 | order.push(5);
41 | cb(null, 5, 5);
42 | }, delay * 5);
43 | });
44 |
45 | async.parallel(tasks, function(err, res) {
46 | if (err) {
47 | return done(err);
48 | }
49 | assert.deepStrictEqual(res, [2, 6, 4, 8, [5, 5]]);
50 | assert.deepStrictEqual(order, [1, 2, 3, 4, 5]);
51 | done();
52 | });
53 | });
54 |
55 | it('should execute in parallel by tasks of object', function(done) {
56 |
57 | var order = [];
58 | var numbers = {
59 | a: 4,
60 | b: 2,
61 | c: 1,
62 | d: 3
63 | };
64 | var tasks = createTasks(order, numbers);
65 |
66 | async.parallel(tasks, function(err, res) {
67 | if (err) {
68 | return done(err);
69 | }
70 | assert.deepStrictEqual(res, {
71 | c: 2,
72 | b: 4,
73 | d: 6,
74 | a: 8
75 | });
76 | assert.deepStrictEqual(order, [1, 2, 3, 4]);
77 | done();
78 | });
79 | });
80 |
81 | it('should execute in parallel by tasks of array without binding', function(done) {
82 |
83 | var order = [];
84 | var numbers = [1.2, 2.4, 1.5, 3.6];
85 | var tasks = createTasks(order, numbers);
86 |
87 | async.parallel(tasks, function(err, res) {
88 | if (err) {
89 | return done(err);
90 | }
91 | assert.deepStrictEqual(res, [2.4, 4.8, 3, 7.2]);
92 | assert.deepStrictEqual(order, [1.2, 1.5, 2.4, 3.6]);
93 | done();
94 | }, Math);
95 | });
96 |
97 | it('should execute in parallel by tasks of object without binding', function(done) {
98 |
99 | var order = [];
100 | var numbers = {
101 | a: 1.2,
102 | b: 2.4,
103 | c: 1.5,
104 | d: 3.6
105 | };
106 | var tasks = createTasks(order, numbers);
107 |
108 | async.parallel(tasks, function(err, res) {
109 | if (err) {
110 | return done(err);
111 | }
112 | assert.deepStrictEqual(res, {
113 | a: 2.4,
114 | c: 3,
115 | b: 4.8,
116 | d: 7.2
117 | });
118 | assert.deepStrictEqual(order, [1.2, 1.5, 2.4, 3.6]);
119 | done();
120 | }, Math);
121 | });
122 |
123 | it('should return response immediately if array task is empty', function(done) {
124 |
125 | var tasks = [];
126 | async.parallel(tasks, function(err, res) {
127 | if (err) {
128 | return done(err);
129 | }
130 | assert.deepStrictEqual(res, []);
131 | done();
132 | });
133 | });
134 |
135 | it('should return response immediately if object task is empty', function(done) {
136 |
137 | var tasks = {};
138 | async.parallel(tasks, function(err, res) {
139 | if (err) {
140 | return done(err);
141 | }
142 | assert.deepStrictEqual(res, {});
143 | done();
144 | });
145 | });
146 |
147 | it('should return response immediately if task is not collection', function(done) {
148 |
149 | async.parallel(null, function(err, res) {
150 | if (err) {
151 | return done(err);
152 | }
153 | assert.strictEqual(res, undefined);
154 | done();
155 | });
156 | });
157 |
158 | it('should throw error', function(done) {
159 |
160 | var order = [];
161 | var numbers = [1, 3, 2, 4];
162 | var tasks = createTasks(order, numbers);
163 | var error = function(callback) {
164 | setTimeout(function() {
165 | callback('error');
166 | }, delay * 2.5);
167 | };
168 | tasks.splice(2, 0, error);
169 |
170 | async.parallel(tasks, function(err) {
171 | assert.ok(err);
172 | assert.deepStrictEqual(order, [1, 2]);
173 | done();
174 | });
175 |
176 | });
177 |
178 | it('should throw error if double callback', function(done) {
179 |
180 | var errorCallCount = 0;
181 | setTimeout(function() {
182 | assert.strictEqual(errorCallCount, 1);
183 | done();
184 | }, delay);
185 |
186 | domain.create()
187 | .on('error', util.errorChecker)
188 | .on('error', function() {
189 | errorCallCount++;
190 | })
191 | .run(function() {
192 | var tasks = [function(next) {
193 | process.nextTick(next);
194 | process.nextTick(next);
195 | }];
196 | async.parallel(tasks);
197 | });
198 | });
199 |
200 | it('should throw error only once', function(done) {
201 |
202 | var error = function(callback) {
203 | setTimeout(function() {
204 | callback('error');
205 | }, delay);
206 | };
207 | var called = false;
208 | var tasks = [error, error, error, error];
209 | async.parallel(tasks, function(err) {
210 | assert.ok(err);
211 | assert.strictEqual(called, false);
212 | called = true;
213 | setTimeout(done, delay * 2);
214 | });
215 | });
216 |
217 | it('should avoid double callback', function(done) {
218 |
219 | var called = false;
220 | var tasks = _.times(3, function(n) {
221 | return function(callback) {
222 | try {
223 | callback('error' + n);
224 | } catch (exception) {
225 | try {
226 | callback(exception);
227 | } catch(e) {
228 | assert.ok(e);
229 | util.errorChecker(e);
230 | }
231 | done();
232 | }
233 | };
234 | });
235 | async.parallel(tasks, function(err) {
236 | assert.ok(err);
237 | assert.strictEqual(called, false);
238 | called = true;
239 | async.nothing();
240 | });
241 | });
242 |
243 | });
244 |
245 | parallel('#parallelLimit', function() {
246 |
247 | it('should execute in limited by tasks of array', function(done) {
248 |
249 | var order = [];
250 | var numbers = [1, 4, 2, 3, 1];
251 | var tasks = createTasks(order, numbers);
252 | tasks.push(function(cb) {
253 | setTimeout(function() {
254 | order.push(5);
255 | cb(null, 5, 5);
256 | }, delay * 1.5);
257 | });
258 |
259 | async.parallelLimit(tasks, 2, function(err, res) {
260 | if (err) {
261 | return done(err);
262 | }
263 | assert.deepStrictEqual(res, [2, 8, 4, 6, 2, [5, 5]]);
264 | assert.deepStrictEqual(order, [1, 2, 4, 1, 3, 5]);
265 | done();
266 | });
267 | });
268 |
269 | it('should execute in limited by tasks of object', function(done) {
270 |
271 | var order = [];
272 | var numbers = {
273 | a: 4,
274 | b: 2,
275 | c: 1,
276 | d: 3,
277 | e: 1
278 | };
279 | var tasks = createTasks(order, numbers);
280 |
281 | async.parallelLimit(tasks, 2, function(err, res) {
282 | if (err) {
283 | return done(err);
284 | }
285 | assert.deepStrictEqual(res, {
286 | b: 4,
287 | a: 8,
288 | c: 2,
289 | d: 6,
290 | e: 2
291 | });
292 | assert.deepStrictEqual(order, [2, 1, 4, 1, 3]);
293 | done();
294 | });
295 | });
296 |
297 | it('should execute in parallel by tasks of array without binding', function(done) {
298 |
299 | var order = [];
300 | var numbers = [1.2, 2.4, 1.5, 3.6];
301 | var tasks = createTasks(order, numbers);
302 |
303 | async.parallelLimit(tasks, 3, function(err, res) {
304 | if (err) {
305 | return done(err);
306 | }
307 | assert.deepStrictEqual(res, [2.4, 4.8, 3, 7.2]);
308 | assert.deepStrictEqual(order, [1.2, 1.5, 2.4, 3.6]);
309 | done();
310 | }, Math);
311 | });
312 |
313 | it('should execute in parallel by tasks of object without binding', function(done) {
314 |
315 | var order = [];
316 | var numbers = {
317 | a: 1.2,
318 | b: 2.4,
319 | c: 1.5,
320 | d: 3.6
321 | };
322 | var tasks = createTasks(order, numbers);
323 |
324 | async.parallelLimit(tasks, 3, function(err, res) {
325 | if (err) {
326 | return done(err);
327 | }
328 | assert.deepStrictEqual(res, {
329 | a: 2.4,
330 | c: 3,
331 | b: 4.8,
332 | d: 7.2
333 | });
334 | assert.deepStrictEqual(order, [1.2, 1.5, 2.4, 3.6]);
335 | done();
336 | }, Math);
337 | });
338 |
339 | it('should execute on asynchronous', function(done) {
340 |
341 | var sync = true;
342 | var numbers = {
343 | a: 4,
344 | b: 2,
345 | c: 1,
346 | d: 3,
347 | e: 1
348 | };
349 | var tasks = _.mapValues(numbers, function(value) {
350 | return function(done) {
351 | done(null, value * 2);
352 | };
353 | });
354 |
355 | async.parallelLimit(tasks, 2, function(err, res) {
356 | if (err) {
357 | return done(err);
358 | }
359 | assert.strictEqual(sync, false);
360 | assert.deepStrictEqual(res, {
361 | b: 4,
362 | a: 8,
363 | c: 2,
364 | d: 6,
365 | e: 2
366 | });
367 | done();
368 | });
369 | sync = false;
370 | });
371 |
372 | it('should return response immediately if array task is empty', function(done) {
373 |
374 | var tasks = [];
375 | async.parallelLimit(tasks, 2, function(err, res) {
376 | if (err) {
377 | return done(err);
378 | }
379 | assert.deepStrictEqual(res, []);
380 | done();
381 | });
382 |
383 | });
384 |
385 | it('should return response immediately if object task is empty', function(done) {
386 |
387 | var tasks = {};
388 | async.parallelLimit(tasks, 2, function(err, res) {
389 | if (err) {
390 | return done(err);
391 | }
392 | assert.deepStrictEqual(res, {});
393 | done();
394 | });
395 |
396 | });
397 |
398 | it('should return response immediately if task is not collection', function(done) {
399 |
400 | async.parallelLimit(null, 2, function(err, res) {
401 | if (err) {
402 | return done(err);
403 | }
404 | assert.strictEqual(res, undefined);
405 | done();
406 | });
407 |
408 | });
409 |
410 | it('should throw error', function(done) {
411 |
412 | var order = [];
413 | var numbers = [1, 3, 2, 4];
414 | var tasks = createTasks(order, numbers);
415 | var error = function(callback) {
416 | setTimeout(function() {
417 | callback('error');
418 | }, delay * 2.5);
419 | };
420 | tasks.splice(2, 0, error);
421 |
422 | async.parallelLimit(tasks, 2, function(err) {
423 | assert.ok(err);
424 | assert.deepStrictEqual(order, [1, 3]);
425 | done();
426 | });
427 |
428 | });
429 |
430 | it('should throw error if double callback', function(done) {
431 |
432 | var errorCallCount = 0;
433 | setTimeout(function() {
434 | assert.strictEqual(errorCallCount, 1);
435 | done();
436 | }, delay);
437 |
438 | domain.create()
439 | .on('error', util.errorChecker)
440 | .on('error', function() {
441 | errorCallCount++;
442 | })
443 | .run(function() {
444 | var tasks = [function(next) {
445 | process.nextTick(next);
446 | process.nextTick(next);
447 | }];
448 | async.parallelLimit(tasks, 4);
449 | });
450 | });
451 |
452 | it('should avoid double callback', function(done) {
453 |
454 | var called = false;
455 | var tasks = _.times(3, function(n) {
456 | return function(callback) {
457 | try {
458 | callback('error' + n);
459 | } catch (exception) {
460 | try {
461 | callback(exception);
462 | } catch(e) {
463 | assert.ok(e);
464 | util.errorChecker(e);
465 | }
466 | done();
467 | }
468 | };
469 | });
470 | async.parallelLimit(tasks, 2, function(err) {
471 | assert.ok(err);
472 | assert.strictEqual(called, false);
473 | called = true;
474 | async.nothing();
475 | });
476 | });
477 |
478 | });
479 |
--------------------------------------------------------------------------------
/test/controlFlow/test.race.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var _ = require('lodash');
7 | var parallel = require('mocha.parallel');
8 |
9 | var async = global.async || require('../../');
10 |
11 | parallel('#race', function() {
12 |
13 | it('should call each funciton in parallel and callback with first result', function(done) {
14 |
15 | var called = 0;
16 | var tasks = _.times(10, function(index) {
17 | return function(next) {
18 | called++;
19 | next(null, index);
20 | };
21 | });
22 | async.race(tasks, function(err, res) {
23 | if (err) {
24 | return done(err);
25 | }
26 | assert.strictEqual(res, 0);
27 | assert.strictEqual(called, 1);
28 | setImmediate(function() {
29 | assert.strictEqual(called, 10);
30 | done();
31 | });
32 | });
33 | });
34 |
35 | it('should callback funciton in parallel with object tasks', function(done) {
36 |
37 | var called = 0;
38 | var tasks = _.mapValues(_.times(5, function(index) {
39 | return function(next) {
40 | setTimeout(function() {
41 | called++;
42 | next(null, index);
43 | }, 50 - index * 5);
44 | };
45 | }));
46 | async.race(tasks, function(err, res) {
47 | if (err) {
48 | return done(err);
49 | }
50 | assert.strictEqual(res, 4);
51 | });
52 | setTimeout(function() {
53 | assert.strictEqual(called, 5);
54 | done();
55 | }, 100);
56 | });
57 |
58 | it('should callback with the first error', function(done) {
59 |
60 | var tasks = _.times(6, function(index) {
61 | return function(next) {
62 | setTimeout(function() {
63 | next(new Error('error:' + index), index);
64 | }, 50 - index * 5);
65 | };
66 | });
67 | async.race(tasks, function(err, res) {
68 | assert.ok(err);
69 | assert.strictEqual(res, 5);
70 | assert.strictEqual(err.message, 'error:5');
71 | done();
72 | });
73 | });
74 |
75 | it('should callback when task is empty', function(done) {
76 |
77 | async.race([], function(err, res) {
78 | if (err) {
79 | return done(err);
80 | }
81 | assert.strictEqual(res, undefined);
82 | done();
83 | });
84 | });
85 |
86 | it('should return TypeError if first argument is not an array or an object', function(done) {
87 |
88 | async.race(null, function(err, res) {
89 | assert.ok(err);
90 | assert.ok(err instanceof TypeError);
91 | assert.strictEqual(res, undefined);
92 | done();
93 | });
94 | });
95 |
96 | });
97 |
--------------------------------------------------------------------------------
/test/controlFlow/test.retry.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = global.async || require('../../');
9 | var delay = require('../config').delay;
10 |
11 | parallel('#retry', function() {
12 |
13 | it('should retry until response', function(done) {
14 |
15 | var failed = 3;
16 | var callCount = 0;
17 | var message = 'success';
18 | var fn = function(callback) {
19 | callCount++;
20 | failed--;
21 | if (failed === 0) {
22 | return callback(null, message);
23 | }
24 | callback('err');
25 | };
26 |
27 | async.retry(fn, function(err, res) {
28 | if (err) {
29 | return done(err);
30 | }
31 | assert.strictEqual(callCount, 3);
32 | assert.strictEqual(res, message);
33 | done();
34 | });
35 | });
36 |
37 | it('should retry until time out', function(done) {
38 |
39 | var times = 3;
40 | var callCount = 0;
41 | var error = 'error';
42 | var success = 'success';
43 | var fn = function(callback) {
44 | callCount++;
45 | callback(error + callCount, success + callCount);
46 | };
47 |
48 | async.retry(times, fn, function(err, res) {
49 | assert.strictEqual(callCount, 3);
50 | assert.strictEqual(err, error + times);
51 | assert.strictEqual(res, success + times);
52 | done();
53 | });
54 | });
55 |
56 | it('should not require a callback', function(done) {
57 |
58 | var times = 3;
59 | var callCount = 0;
60 | var fn = function(callback) {
61 | callCount++;
62 | callback();
63 | };
64 | async.retry(times, fn);
65 | setTimeout(function() {
66 | assert.strictEqual(callCount, 1);
67 | done();
68 | }, delay);
69 | });
70 |
71 | it('should execute even if type of times is string', function(done) {
72 |
73 | var times = '3';
74 | var callCount = 0;
75 | var fn = function(callback) {
76 | callCount++;
77 | callback();
78 | };
79 | async.retry(times, fn);
80 | setTimeout(function() {
81 | assert.strictEqual(callCount, 1);
82 | done();
83 | }, delay);
84 | });
85 |
86 | it('should throw error if arguments are empty', function() {
87 |
88 | try {
89 | async.retry();
90 | } catch(e) {
91 | assert.ok(e);
92 | assert.strictEqual(e.message, 'Invalid arguments for async.retry');
93 | }
94 | });
95 |
96 | it('should throw error if first argument is not function', function() {
97 |
98 | try {
99 | async.retry(1);
100 | } catch(e) {
101 | assert.ok(e);
102 | assert.strictEqual(e.message, 'Invalid arguments for async.retry');
103 | }
104 | });
105 |
106 | it('should throw error if arguments are invalid', function() {
107 |
108 | try {
109 | async.retry(function() {}, 2, function() {});
110 | } catch(e) {
111 | assert.ok(e);
112 | assert.strictEqual(e.message, 'Invalid arguments for async.retry');
113 | }
114 | });
115 |
116 | it('should retry with interval when all attempts succeeds', function(done) {
117 |
118 | var times = 3;
119 | var interval = delay * 3;
120 | var callCount = 0;
121 | var error = 'ERROR';
122 | var erroredResult = 'RESULT';
123 | var fn = function(callback) {
124 | callCount++;
125 | callback(error + callCount, erroredResult + callCount);
126 | };
127 | var opts = {
128 | times: times,
129 | interval: interval
130 | };
131 | var start = Date.now();
132 | async.retry(opts, fn, function(err, res) {
133 | var diff = Date.now() - start;
134 | assert(diff >= (interval * (times - 1)));
135 | assert.strictEqual(callCount, 3);
136 | assert.strictEqual(err, error + times);
137 | assert.strictEqual(res, erroredResult + times);
138 | done();
139 | });
140 | });
141 |
142 | it('should retry with empty options', function(done) {
143 |
144 | var callCount = 0;
145 | var fn = function(callback) {
146 | callCount++;
147 | callback('error');
148 | };
149 | var opts = {};
150 | async.retry(opts, fn, function(err) {
151 | assert.ok(err);
152 | assert.strictEqual(callCount, 5);
153 | done();
154 | });
155 | });
156 |
157 | it('should use default times', function(done) {
158 |
159 | var called = 0;
160 | async.retry(function(callback) {
161 | called++;
162 | callback('error');
163 | });
164 | setTimeout(function() {
165 | assert.strictEqual(called, 5);
166 | done();
167 | }, delay);
168 | });
169 |
170 | it('retry with custom interval when all attempts fail',function(done) {
171 | var times = 3;
172 | var intervalFunc = function(retryCount) {
173 | return retryCount * 110;
174 | };
175 | var callCount = 0;
176 | var error = 'ERROR';
177 | var erroredResult = 'RESULT';
178 | var iterator = function(callback) {
179 | callCount++;
180 | callback(error + callCount, erroredResult + callCount); // respond with indexed values
181 | };
182 | var opts = {
183 | times: times,
184 | interval: intervalFunc
185 | };
186 | var start = Date.now();
187 | async.retry(opts, iterator, function(err, res) {
188 | var now = Date.now();
189 | var diff = now - start;
190 | assert.ok(diff >= 300, diff);
191 | assert.strictEqual(callCount, 3);
192 | assert.strictEqual(err, error + times);
193 | assert.strictEqual(res, erroredResult + times);
194 | done();
195 | });
196 | });
197 |
198 | it('should return extra arguments', function(done) {
199 | var func = function(callback) {
200 | callback(null, 1, 2, 3);
201 | };
202 | async.retry(5, func, function(err, arg1, arg2, arg3) {
203 | if (err) {
204 | return done(err);
205 | }
206 | assert.strictEqual(arguments.length, 4);
207 | assert.strictEqual(arg1, 1);
208 | assert.strictEqual(arg2, 2);
209 | assert.strictEqual(arg3, 3);
210 | done();
211 | });
212 | });
213 |
214 | it('should return extra arguments with options', function(done) {
215 | var func = function(callback) {
216 | callback(null, 1, 2, 3);
217 | };
218 | var intervalFunc = function(retryCount) {
219 | return retryCount * 110;
220 | };
221 | var opts = {
222 | times: 5,
223 | interval: intervalFunc
224 | };
225 | async.retry(opts, func, function(err, arg1, arg2, arg3) {
226 | if (err) {
227 | return done(err);
228 | }
229 | assert.strictEqual(arguments.length, 4);
230 | assert.strictEqual(arg1, 1);
231 | assert.strictEqual(arg2, 2);
232 | assert.strictEqual(arg3, 3);
233 | done();
234 | });
235 | });
236 |
237 | it('should use default interval if interval is invalid string or number', function(done) {
238 | var callCount = 0;
239 | var func = function(callback) {
240 | callback(++callCount % 2, callCount);
241 | };
242 | var opts = {
243 | interval: 'test'
244 | };
245 | async.retry(opts, func, function(err, res) {
246 | if (err) {
247 | return done(err);
248 | }
249 | assert.strictEqual(res, 2);
250 | assert.strictEqual(callCount, 2);
251 | done();
252 | });
253 | });
254 |
255 | it('retry when some attempts fail and error test returns false at some invokation',function(done) {
256 | var callCount = 0;
257 | var error = 'ERROR';
258 | var special = 'SPECIAL_ERROR';
259 | var erroredResult = 'RESULT';
260 | function fn(callback) {
261 | callCount++;
262 | var err = callCount === 2 ? special : error + callCount;
263 | callback(err, erroredResult + callCount);
264 | }
265 | function errorTest(err) {
266 | return err && err === error + callCount; // just a different pattern
267 | }
268 | var options = {
269 | errorFilter: errorTest
270 | };
271 | async.retry(options, fn, function(err, result) {
272 | assert.equal(callCount, 2, 'did not retry the correct number of times');
273 | assert.equal(err, special, 'Incorrect error was returned');
274 | assert.equal(result, erroredResult + 2, 'Incorrect result was returned');
275 | done();
276 | });
277 | });
278 |
279 | it('retry with interval when some attempts fail and error test returns false at some invokation',function(done) {
280 | var interval = 50;
281 | var callCount = 0;
282 | var error = 'ERROR';
283 | var erroredResult = 'RESULT';
284 | var special = 'SPECIAL_ERROR';
285 | var specialCount = 3;
286 | function fn(callback) {
287 | callCount++;
288 | var err = callCount === specialCount ? special : error + callCount;
289 | callback(err, erroredResult + callCount);
290 | }
291 | function errorTest(err) {
292 | return err && err !== special;
293 | }
294 | var start = new Date().getTime();
295 | async.retry({ interval: interval, errorFilter: errorTest }, fn, function(err, result){
296 | var now = new Date().getTime();
297 | var duration = now - start;
298 | assert(duration >= (interval * (specialCount - 1)), 'did not include interval');
299 | assert.equal(callCount, specialCount, 'did not retry the correct number of times');
300 | assert.equal(err, special, 'Incorrect error was returned');
301 | assert.equal(result, erroredResult + specialCount, 'Incorrect result was returned');
302 | done();
303 | });
304 | });
305 |
306 | });
307 |
--------------------------------------------------------------------------------
/test/controlFlow/test.retryable.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = global.async || require('../../');
9 | var delay = require('../config').delay;
10 |
11 | parallel('#retryable', function() {
12 |
13 | it('should retry', function(done) {
14 |
15 | var callCount = 0;
16 | var retryableTask = async.retryable(3, function(arg, callback) {
17 | callCount++;
18 | assert.strictEqual(arg, 42);
19 | callback('fail', callCount);
20 | });
21 | retryableTask(42, function(err, res) {
22 | assert.ok(err);
23 | assert.strictEqual(res, 3);
24 | done();
25 | });
26 | });
27 |
28 | it('should work as an embedded task', function(done) {
29 |
30 | var retryResult = 'RETRY';
31 | var fooResults;
32 | var retryResults;
33 | async.auto({
34 | dep: async.constant('dep'),
35 | foo: ['dep', function(res, callback) {
36 | fooResults = res;
37 | callback(null, 'FOO');
38 | }],
39 | retry: ['dep', async.retryable(function(res, callback) {
40 | retryResults = res;
41 | callback(null, retryResult);
42 | })]
43 | }, function(err, res) {
44 | if (err) {
45 | return done(err);
46 | }
47 | assert.strictEqual(res.retry, retryResult);
48 | assert.strictEqual(fooResults, retryResults);
49 | done();
50 | });
51 | });
52 |
53 | it('should execute even if callback function length is more than 2', function(done) {
54 |
55 | async.autoInject({
56 | a: [async.retryable(function(callback) {
57 | callback(null, 'a');
58 | })],
59 | b: ['a', async.retryable(function(a, callback) {
60 | callback(null, 'b');
61 | })],
62 | c: ['a', 'b', async.retryable(function(a, b, callback) {
63 | callback(null, 'c');
64 | })],
65 | d: ['a', 'b', 'c', async.retryable(function(a, b, c, callback) {
66 | callback(null, 'd');
67 | })],
68 | e: ['a', 'b', 'c', 'd', async.retryable(function(a, b, c, d, callback) {
69 | callback(null, 'e');
70 | })],
71 | f: ['a', 'b', 'c', 'd', 'e', async.retryable(function(a, b, c, d, e, callback) {
72 | callback(null, 'f');
73 | })]
74 | }, function(err, res) {
75 | if (err) {
76 | return done(err);
77 | }
78 | assert.deepStrictEqual(res, {
79 | a: 'a',
80 | b: 'b',
81 | c: 'c',
82 | d: 'd',
83 | e: 'e',
84 | f: 'f'
85 | });
86 | done();
87 | });
88 | });
89 |
90 | it('should work as sn embedded task with interval', function(done) {
91 |
92 | var start = Date.now();
93 | var opts = {
94 | times: 3,
95 | interval: delay * 3
96 | };
97 | async.auto({
98 | foo: function(callback) {
99 | callback(null, 'FOO');
100 | },
101 | retry: async.retryable(opts, function(callback) {
102 | callback('err');
103 | })
104 | }, function(err) {
105 | assert.ok(err);
106 | var diff = Date.now() - start;
107 | assert(diff > delay * (opts.times - 1));
108 | done();
109 | });
110 | });
111 |
112 | });
113 |
--------------------------------------------------------------------------------
/test/controlFlow/test.seq.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = global.async || require('../../');
9 | var delay = require('../config').delay;
10 |
11 | parallel('#seq', function() {
12 |
13 | it('should execute in order of insertion', function(done) {
14 |
15 | var add2 = function(n, cb) {
16 | assert.strictEqual(n, 3);
17 | setTimeout(function() {
18 | cb(null, n + 2);
19 | }, 50);
20 | };
21 | var mul3 = function(n, cb) {
22 | assert.strictEqual(n, 5);
23 | setTimeout(function() {
24 | cb(null, n * 3);
25 | }, 15);
26 | };
27 | var add1 = function(n, cb) {
28 | assert.strictEqual(n, 15);
29 | setTimeout(function() {
30 | cb(null, n + 1);
31 | }, 100);
32 | };
33 | var add2mul3add1 = async.seq(add2, mul3, add1);
34 |
35 | add2mul3add1(3, function(err, res) {
36 | if (err) {
37 | return done(err);
38 | }
39 | assert.strictEqual(res, 16);
40 | done();
41 | });
42 | });
43 |
44 | it('should execute in order of insertion with binding', function(done) {
45 |
46 | var pow2 = function(n, cb) {
47 | var self = this;
48 | assert.strictEqual(n, 3);
49 | setTimeout(function() {
50 | cb(null, self.pow(n, 2));
51 | }, 50);
52 | };
53 | var mul3 = function(n, cb) {
54 | assert.strictEqual(n, 9);
55 | setTimeout(function() {
56 | cb(null, n * 3);
57 | }, 15);
58 | };
59 | var pow3 = function(n, cb) {
60 | var self = this;
61 | assert.strictEqual(n, 27);
62 | setTimeout(function() {
63 | cb(null, self.pow(n, 3));
64 | }, 100);
65 | };
66 |
67 | var add2mul3add1 = async.seq(pow2, mul3, pow3);
68 |
69 | add2mul3add1.call(Math, 3, function(err, res) {
70 | if (err) {
71 | return done(err);
72 | }
73 | assert.strictEqual(res, 19683);
74 | done();
75 | });
76 | });
77 |
78 | it('should execute without callback', function(done) {
79 |
80 | var testcontext = {
81 | name: 'foo'
82 | };
83 | var add2 = function (n, cb) {
84 | assert.strictEqual(this, testcontext);
85 | setTimeout(function () {
86 | cb(null, n + 2);
87 | }, delay * 2);
88 | };
89 | var mul3 = function () {
90 | assert.strictEqual(this, testcontext);
91 | setTimeout(done, delay);
92 | };
93 | var add2mul3 = async.seq(add2, mul3);
94 | add2mul3.call(testcontext, 3);
95 | });
96 |
97 | it('should throw error', function(done) {
98 |
99 | var add2 = function(n, cb) {
100 | assert.strictEqual(n, 3);
101 | setTimeout(function() {
102 | cb(null, n + 2);
103 | }, 50);
104 | };
105 | var mul3 = function(n, cb) {
106 | assert.strictEqual(n, 5);
107 | setTimeout(function() {
108 | cb(new Error('error'));
109 | }, 15);
110 | };
111 | var add1 = function(n, cb) {
112 | setTimeout(function() {
113 | cb(null, n + 1);
114 | }, 100);
115 | };
116 | var add2mul3add1 = async.seq(add2, mul3, add1);
117 |
118 | add2mul3add1(3, function(err) {
119 | assert.ok(err);
120 | done();
121 | });
122 | });
123 |
124 | });
125 |
--------------------------------------------------------------------------------
/test/controlFlow/test.series.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 | var domain = require('domain');
6 |
7 | var _ = require('lodash');
8 | var parallel = require('mocha.parallel');
9 |
10 | var async = global.async || require('../../');
11 | var delay = require('../config').delay;
12 | var util = require('../util');
13 |
14 | function createTasks(order, numbers) {
15 |
16 | return _.transform(numbers, function(memo, num, index) {
17 | memo[index] = function(callback) {
18 | var self = this;
19 | setTimeout(function() {
20 | order.push(num);
21 | if (self && self.round) {
22 | num = self.round(num);
23 | }
24 | callback(null, num * 2);
25 | }, num * delay);
26 | };
27 | });
28 | }
29 |
30 | parallel('#series', function() {
31 |
32 | it('should execute to series by tasks of array', function(done) {
33 |
34 | var order = [];
35 | var numbers = [1, 3, 2, 4];
36 | var tasks = createTasks(order, numbers);
37 | tasks.push(function(cb) {
38 | setTimeout(function() {
39 | order.push(5);
40 | cb(null, 5, 5);
41 | }, delay * 5);
42 | });
43 |
44 | async.series(tasks, function(err, res) {
45 | if (err) {
46 | return done(err);
47 | }
48 | assert.deepStrictEqual(res, [2, 6, 4, 8, [5, 5]]);
49 | assert.deepStrictEqual(order, [1, 3, 2, 4, 5]);
50 | done();
51 | });
52 | });
53 |
54 | it('should execute to series by tasks of object', function(done) {
55 |
56 | var order = [];
57 | var numbers = {
58 | a: 4,
59 | b: 2,
60 | c: 1,
61 | d: 3
62 | };
63 | var tasks = createTasks(order, numbers);
64 |
65 | async.series(tasks, function(err, res) {
66 | if (err) {
67 | return done(err);
68 | }
69 | assert.deepStrictEqual(res, {
70 | a: 8,
71 | b: 4,
72 | c: 2,
73 | d: 6
74 | });
75 | assert.deepStrictEqual(order, [4, 2, 1, 3]);
76 | done();
77 | });
78 | });
79 |
80 | it('should execute to series by tasks of array without binding', function(done) {
81 |
82 | var order = [];
83 | var numbers = [1.2, 2.4, 1.5, 3.6];
84 | var tasks = createTasks(order, numbers);
85 |
86 | async.series(tasks, function(err, res) {
87 | if (err) {
88 | return done(err);
89 | }
90 | assert.deepStrictEqual(res, [2.4, 4.8, 3, 7.2]);
91 | assert.deepStrictEqual(order, [1.2, 2.4, 1.5, 3.6]);
92 | done();
93 | }, Math);
94 | });
95 |
96 | it('should execute to series by tasks of object without binding', function(done) {
97 |
98 | var order = [];
99 | var numbers = {
100 | a: 1.2,
101 | b: 2.4,
102 | c: 1.5,
103 | d: 3.6
104 | };
105 | var tasks = createTasks(order, numbers);
106 |
107 | async.series(tasks, function(err, res) {
108 | if (err) {
109 | return done(err);
110 | }
111 | assert.deepStrictEqual(res, {
112 | a: 2.4,
113 | b: 4.8,
114 | c: 3,
115 | d: 7.2
116 | });
117 | assert.deepStrictEqual(order, [1.2, 2.4, 1.5, 3.6]);
118 | done();
119 | }, Math);
120 | });
121 |
122 | it('should execute on asynchronous', function(done) {
123 |
124 | var sync = true;
125 | var numbers = [1, 3, 2, 4];
126 | var tasks = _.map(numbers, function(n) {
127 | return function(next) {
128 | next(null, n);
129 | };
130 | });
131 | async.series(tasks, function(err, res) {
132 | if (err) {
133 | return done(err);
134 | }
135 | assert.strictEqual(sync, false);
136 | assert.deepStrictEqual(res, [1, 3, 2, 4]);
137 | done();
138 | });
139 | sync = false;
140 | });
141 |
142 | it('should return response immediately if array task is empty', function(done) {
143 |
144 | var tasks = [];
145 | async.series(tasks, function(err, res) {
146 | if (err) {
147 | return done(err);
148 | }
149 | assert.deepStrictEqual(res, []);
150 | done();
151 | });
152 | });
153 |
154 | it('should return response immediately if object task is empty', function(done) {
155 |
156 | var tasks = {};
157 | async.series(tasks, function(err, res) {
158 | if (err) {
159 | return done(err);
160 | }
161 | assert.deepStrictEqual(res, {});
162 | done();
163 | });
164 | });
165 |
166 | it('should return response immediately if task is not collection', function(done) {
167 |
168 | async.series('test', function(err, res) {
169 | if (err) {
170 | return done(err);
171 | }
172 | assert.strictEqual(res, undefined);
173 | done();
174 | });
175 | });
176 |
177 | it('should throw error', function(done) {
178 |
179 | var order = [];
180 | var numbers = [1, 3, 2, 4];
181 | var tasks = createTasks(order, numbers);
182 | var errorTask = function(next) {
183 | next('error');
184 | };
185 | tasks.splice(2, 0, errorTask);
186 |
187 | async.series(tasks, function(err) {
188 | assert.ok(err);
189 | done();
190 | });
191 | });
192 |
193 | it('should throw error if double callback', function(done) {
194 |
195 | var errorCallCount = 0;
196 | setTimeout(function() {
197 | assert.strictEqual(errorCallCount, 1);
198 | done();
199 | }, delay);
200 |
201 | domain.create()
202 | .on('error', util.errorChecker)
203 | .on('error', function() {
204 | errorCallCount++;
205 | })
206 | .run(function() {
207 | var tasks = [function(next) {
208 | process.nextTick(next);
209 | process.nextTick(next);
210 | }];
211 | async.series(tasks);
212 | });
213 | });
214 |
215 | it('should avoid double callback', function(done) {
216 |
217 | var called = false;
218 | var tasks = _.times(3, function(n) {
219 | return function(callback) {
220 | try {
221 | callback('error' + n);
222 | } catch (exception) {
223 | try {
224 | callback(exception);
225 | } catch(e) {
226 | assert.ok(e);
227 | util.errorChecker(e);
228 | }
229 | done();
230 | }
231 | };
232 | });
233 | async.series(tasks, function(err) {
234 | assert.ok(err);
235 | assert.strictEqual(called, false);
236 | called = true;
237 | async.nothing();
238 | });
239 | });
240 |
241 | });
242 |
--------------------------------------------------------------------------------
/test/controlFlow/test.timeout.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = global.async || require('../../');
9 | var delay = require('../config').delay;
10 |
11 | parallel('#timeout', function() {
12 |
13 | it('timeout with series', function(done) {
14 | async.series([
15 | async.timeout(function(callback) {
16 | setTimeout(function() {
17 | callback(null, 'I did not time out');
18 | }, delay);
19 | }, delay * 2),
20 | async.timeout(function(callback) {
21 | setTimeout(function() {
22 | callback(null, 'I will time out');
23 | }, delay * 3);
24 | }, delay * 2)
25 | ], function(err, res) {
26 | assert.ok(err);
27 | assert.strictEqual(err.code, 'ETIMEDOUT');
28 | assert.strictEqual(err.message, 'Callback function "anonymous" timed out.');
29 | assert.strictEqual(res[0], 'I did not time out');
30 | done();
31 | });
32 | });
33 |
34 | it('timeout with parallel', function(done) {
35 |
36 | var info = { info: 'info' };
37 | async.parallel([
38 | async.timeout(function(callback) {
39 | setTimeout(function() {
40 | callback(null, 'I did not time out');
41 | }, delay);
42 | }, delay * 2),
43 | async.timeout(function timer(callback) {
44 | setTimeout(function() {
45 | callback(null, 'I will time out');
46 | }, delay * 3);
47 | }, delay * 2, info)
48 | ], function(err, res) {
49 | assert.ok(err);
50 | assert.strictEqual(err.code, 'ETIMEDOUT');
51 | assert.strictEqual(err.message, 'Callback function "timer" timed out.');
52 | assert.strictEqual(err.info, info);
53 | assert.strictEqual(res[0], 'I did not time out');
54 | done();
55 | });
56 | });
57 |
58 | it('should throw error', function(done) {
59 |
60 | async.parallel([
61 | async.timeout(function(callback) {
62 | setTimeout(function() {
63 | callback();
64 | }, delay);
65 | }, delay * 2),
66 | async.timeout(function(callback) {
67 | setTimeout(function() {
68 | callback(null, 2, 2, 2);
69 | }, delay);
70 | }, delay * 2),
71 | async.timeout(function(callback) {
72 | setTimeout(function() {
73 | callback(new Error('error'));
74 | }, delay * 2);
75 | }, delay * 4)
76 | ], function(err) {
77 | assert.ok(err);
78 | assert.strictEqual(err.message, 'error');
79 | done();
80 | });
81 | });
82 |
83 | });
84 |
--------------------------------------------------------------------------------
/test/controlFlow/test.times.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 | var domain = require('domain');
6 |
7 | var parallel = require('mocha.parallel');
8 |
9 | var async = global.async || require('../../');
10 | var delay = require('../config').delay;
11 | var util = require('../util');
12 |
13 | function timeItrator(order) {
14 |
15 | return function(num, callback) {
16 |
17 | var self = this;
18 |
19 | setTimeout(function() {
20 |
21 | order.push(num);
22 | if (self && self.pow) {
23 | num = self.pow(num, 2);
24 | }
25 |
26 | callback(null, num);
27 | }, num % 2 === 0 ? delay : 3 * delay);
28 | };
29 | }
30 |
31 | parallel('#times', function() {
32 |
33 | it('should execute iterator', function(done) {
34 |
35 | var n = 3;
36 | var order = [];
37 | async.times(n, timeItrator(order), function(err, res) {
38 | if (err) {
39 | return done(err);
40 | }
41 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
42 | assert.deepStrictEqual(res, [0, 1, 2]);
43 | assert.deepStrictEqual(order, [0, 2, 1]);
44 | done();
45 | });
46 | });
47 |
48 | it('should execute iterator even if num is string', function(done) {
49 |
50 | var n = '3';
51 | var order = [];
52 | async.times(n, timeItrator(order), function(err, res) {
53 | if (err) {
54 | return done(err);
55 | }
56 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
57 | assert.deepStrictEqual(res, [0, 1, 2]);
58 | assert.deepStrictEqual(order, [0, 2, 1]);
59 | done();
60 | });
61 | });
62 |
63 | it('should execute iterator without binding', function(done) {
64 |
65 | var n = 3;
66 | var order = [];
67 | async.times(n, timeItrator(order), function(err, res) {
68 | if (err) {
69 | return done(err);
70 | }
71 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
72 | assert.deepStrictEqual(res, [0, 1, 2]);
73 | assert.deepStrictEqual(order, [0, 2, 1]);
74 | done();
75 | }, Math);
76 | });
77 |
78 | it('should return response immediately', function(done) {
79 |
80 | var n = 0;
81 | var order = [];
82 | async.times(n, timeItrator(order), function(err, res) {
83 | if (err) {
84 | return done(err);
85 | }
86 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
87 | assert.deepStrictEqual(res, []);
88 | assert.deepStrictEqual(order, []);
89 | done();
90 | });
91 | });
92 |
93 | it('should throw error', function(done) {
94 |
95 | var n = 4;
96 | var iterator = function(n, next) {
97 | next(n === 2);
98 | };
99 | async.times(n, iterator, function(err) {
100 | assert.ok(err);
101 | setTimeout(done, delay);
102 | });
103 | });
104 |
105 | it('should throw error if double callback', function(done) {
106 |
107 | var errorCallCount = 0;
108 | setTimeout(function() {
109 | assert.strictEqual(errorCallCount, 4);
110 | done();
111 | }, delay);
112 |
113 | domain.create()
114 | .on('error', util.errorChecker)
115 | .on('error', function() {
116 | errorCallCount++;
117 | })
118 | .run(function() {
119 | var iterator = function(num, callback) {
120 | process.nextTick(callback);
121 | process.nextTick(callback);
122 | };
123 | async.times(4, iterator);
124 | });
125 | });
126 |
127 | });
128 |
129 | parallel('#timesSeries', function() {
130 |
131 | it('should execute iterator', function(done) {
132 |
133 | var n = 3;
134 | var order = [];
135 | async.timesSeries(n, timeItrator(order), function(err, res) {
136 | if (err) {
137 | return done(err);
138 | }
139 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
140 | assert.deepStrictEqual(res, [0, 1, 2]);
141 | assert.deepStrictEqual(order, [0, 1, 2]);
142 | done();
143 | });
144 | });
145 |
146 | it('should execute iterator even if num is string', function(done) {
147 |
148 | var n = '3';
149 | var order = [];
150 | async.timesSeries(n, timeItrator(order), function(err, res) {
151 | if (err) {
152 | return done(err);
153 | }
154 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
155 | assert.deepStrictEqual(res, [0, 1, 2]);
156 | assert.deepStrictEqual(order, [0, 1, 2]);
157 | done();
158 | });
159 | });
160 |
161 | it('should execute iterator without binding', function(done) {
162 |
163 | var n = 3;
164 | var order = [];
165 | async.timesSeries(n, timeItrator(order), function(err, res) {
166 | if (err) {
167 | return done(err);
168 | }
169 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
170 | assert.deepStrictEqual(res, [0, 1, 2]);
171 | assert.deepStrictEqual(order, [0, 1, 2]);
172 | done();
173 | }, Math);
174 | });
175 |
176 | it('should execute on asynchronous', function(done) {
177 |
178 | var sync = true;
179 | var n = 3;
180 | var iterator = function(n, callback) {
181 | callback(null, n);
182 | };
183 | async.timesSeries(n, iterator, function(err, result) {
184 | if (err) {
185 | return done(err);
186 | }
187 | assert.strictEqual(sync, false);
188 | assert.deepStrictEqual(result, [0, 1, 2]);
189 | done();
190 | });
191 | sync = false;
192 | });
193 |
194 | it('should return response immediately', function(done) {
195 |
196 | var n = 0;
197 | var order = [];
198 | async.timesSeries(n, timeItrator(order), function(err, res) {
199 | if (err) {
200 | return done(err);
201 | }
202 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
203 | assert.deepStrictEqual(res, []);
204 | assert.deepStrictEqual(order, []);
205 | done();
206 | });
207 | });
208 |
209 | it('should throw error', function(done) {
210 |
211 | var n = 4;
212 | var iterator = function(n, next) {
213 | next(n === 2);
214 | };
215 | async.timesSeries(n, iterator, function(err) {
216 | assert.ok(err);
217 | done();
218 | });
219 | });
220 |
221 | it('should throw error if double callback', function(done) {
222 |
223 | var errorCallCount = 0;
224 | setTimeout(function() {
225 | assert.strictEqual(errorCallCount, 4);
226 | done();
227 | }, delay);
228 |
229 | domain.create()
230 | .on('error', util.errorChecker)
231 | .on('error', function() {
232 | errorCallCount++;
233 | })
234 | .run(function() {
235 | var iterator = function(num, callback) {
236 | process.nextTick(callback);
237 | process.nextTick(callback);
238 | };
239 | async.timesSeries(4, iterator);
240 | });
241 | });
242 |
243 | });
244 |
245 | parallel('#timesLimit', function() {
246 |
247 | it('should execute iterator', function(done) {
248 |
249 | var n = 5;
250 | var order = [];
251 | async.timesLimit(n, 2, timeItrator(order), function(err, res) {
252 | if (err) {
253 | return done(err);
254 | }
255 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
256 | assert.deepStrictEqual(res, [0, 1, 2, 3, 4]);
257 | assert.deepStrictEqual(order, [0, 2, 1, 4, 3]);
258 | done();
259 | });
260 | });
261 |
262 | it('should execute iterator even if num is string', function(done) {
263 |
264 | var n = '5';
265 | var order = [];
266 | async.timesLimit(n, 2, timeItrator(order), function(err, res) {
267 | if (err) {
268 | return done(err);
269 | }
270 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
271 | assert.deepStrictEqual(res, [0, 1, 2, 3, 4]);
272 | assert.deepStrictEqual(order, [0, 2, 1, 4, 3]);
273 | done();
274 | });
275 | });
276 |
277 | it('should execute iterator without binding', function(done) {
278 |
279 | var n = 7;
280 | var order = [];
281 | async.timesLimit(n, 2, timeItrator(order), function(err, res) {
282 | if (err) {
283 | return done(err);
284 | }
285 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
286 | assert.deepStrictEqual(res, [0, 1, 2, 3, 4, 5, 6]);
287 | assert.deepStrictEqual(order, [0, 2, 1, 4, 3, 6, 5]);
288 | done();
289 | }, Math);
290 | });
291 |
292 | it('should execute like parallel if limit is Infinity', function(done) {
293 |
294 | var n = 5;
295 | var order = [];
296 | var iterator = function(n, done) {
297 | setTimeout(function() {
298 | order.push(n);
299 | done(null, n);
300 | }, n * 30);
301 | };
302 | async.timesLimit(n, Infinity, iterator, function(err, res) {
303 | if (err) {
304 | return done(err);
305 | }
306 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
307 | assert.deepStrictEqual(res, [0, 1, 2, 3, 4]);
308 | assert.deepStrictEqual(order, [0, 1, 2, 3, 4]);
309 | done();
310 | });
311 | });
312 |
313 | it('should return response immediately', function(done) {
314 |
315 | var n = 0;
316 | var order = [];
317 | async.timesLimit(n, 2, timeItrator(order), function(err, res) {
318 | if (err) {
319 | return done(err);
320 | }
321 | assert.strictEqual(Object.prototype.toString.call(res), '[object Array]');
322 | assert.deepStrictEqual(res, []);
323 | assert.deepStrictEqual(order, []);
324 | done();
325 | });
326 | });
327 |
328 | it('should execute on asynchronous', function(done) {
329 |
330 | var sync = true;
331 | var n = 5;
332 | var iterator = function(n, callback) {
333 | callback(null, n);
334 | };
335 | async.timesLimit(n, 2, iterator, function(err, result) {
336 | if (err) {
337 | return done(err);
338 | }
339 | assert.strictEqual(sync, false);
340 | assert.deepStrictEqual(result, [0, 1, 2, 3, 4]);
341 | done();
342 | });
343 | sync = false;
344 | });
345 |
346 | it('should throw error', function(done) {
347 |
348 | var n = 6;
349 | var iterator = function(n, next) {
350 | next(n === 4);
351 | };
352 | async.timesLimit(n, 3, iterator, function(err) {
353 | assert.ok(err);
354 | setTimeout(done, delay);
355 | });
356 | });
357 |
358 | it('should throw error if double callback', function(done) {
359 |
360 | var errorCallCount = 0;
361 | setTimeout(function() {
362 | assert.strictEqual(errorCallCount, 4);
363 | done();
364 | }, delay);
365 |
366 | domain.create()
367 | .on('error', util.errorChecker)
368 | .on('error', function() {
369 | errorCallCount++;
370 | })
371 | .run(function() {
372 | var iterator = function(num, callback) {
373 | process.nextTick(callback);
374 | process.nextTick(callback);
375 | };
376 | async.timesLimit(4, 2, iterator);
377 | });
378 | });
379 |
380 | });
381 |
--------------------------------------------------------------------------------
/test/controlFlow/test.tryEach.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = global.async || require('../../');
9 |
10 | parallel('#tryEach', function() {
11 |
12 | it('should execute', function(done) {
13 |
14 | var result = 'test';
15 | async.tryEach([
16 | function(callback) {
17 | callback(null, result);
18 | }
19 | ], function(err, res) {
20 | if (err) {
21 | return done(err);
22 | }
23 | assert.strictEqual(res, result);
24 | done();
25 | });
26 | });
27 |
28 | it('should execute with object', function(done) {
29 |
30 | var result = 'test';
31 | async.tryEach({
32 | task1: function(callback) {
33 | callback(null, result);
34 | },
35 | task2: function() {
36 | assert(false);
37 | }
38 | }, function(err, res) {
39 | if (err) {
40 | return done(err);
41 | }
42 | assert.strictEqual(res, result);
43 | done();
44 | });
45 | });
46 |
47 | it('should return multiple arguments', function(done) {
48 |
49 | var results = ['arg1', 'arg2'];
50 | async.tryEach([
51 | function(callback) {
52 | callback(null, results[0], results[1]);
53 | }
54 | ], function(err, res) {
55 | if (err) {
56 | return done(err);
57 | }
58 | assert.deepStrictEqual(res, results);
59 | done();
60 | });
61 | });
62 |
63 | it('should execute second task if first task is failed', function(done) {
64 |
65 | async.tryEach([
66 | function(callback) {
67 | callback(new Error('failed'), 'task1');
68 | },
69 | function(callback) {
70 | callback(null, 'task2');
71 | }
72 | ], function(err, res) {
73 | if (err) {
74 | return done(err);
75 | }
76 | assert.strictEqual(res, 'task2');
77 | done();
78 | });
79 |
80 | });
81 |
82 | it('should return an error if all tasks are failed', function(done) {
83 |
84 | async.tryEach([
85 | function(callback) {
86 | callback(new Error('failed1'), 'task1');
87 | },
88 | function(callback) {
89 | callback(new Error('failed2'), 'task2');
90 | }
91 | ], function(err) {
92 | assert.ok(err);
93 | assert.strictEqual(err.message, 'failed2');
94 | done();
95 | });
96 | });
97 |
98 | it('should not cause any error if task is empty', function(done) {
99 |
100 | async.tryEach([], function(err, res) {
101 | if (err) {
102 | return done(err);
103 | }
104 | assert.strictEqual(res, undefined);
105 | done();
106 | });
107 | });
108 |
109 | it('should not cause any error if task is string', function(done) {
110 |
111 | async.tryEach('test', function(err, res) {
112 | if (err) {
113 | return done(err);
114 | }
115 | assert.strictEqual(res, undefined);
116 | done();
117 | });
118 | });
119 | });
120 |
--------------------------------------------------------------------------------
/test/controlFlow/test.until.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var _ = require('lodash');
7 | var parallel = require('mocha.parallel');
8 |
9 | var async = global.async || require('../../');
10 |
11 | parallel('#until', function() {
12 |
13 | it('should execute until test is true', function(done) {
14 |
15 | var count = 0;
16 | var limit = 5;
17 | var order = {
18 | test: [],
19 | iterator: []
20 | };
21 | var test = function() {
22 | order.test.push(count);
23 | return count === limit;
24 | };
25 | var iterator = function(callback) {
26 | order.iterator.push(count++);
27 | callback(null, count);
28 | };
29 |
30 | async.until(test, iterator, function(err, res) {
31 | if (err) {
32 | return done(err);
33 | }
34 |
35 | assert.deepStrictEqual(order.iterator, [0, 1, 2, 3, 4]);
36 | assert.deepStrictEqual(order.test, [0, 1, 2, 3, 4, 5]);
37 | assert.strictEqual(res, 5);
38 | done();
39 | });
40 | });
41 |
42 | it('should execute without binding until test is false', function(done) {
43 |
44 | var count = 0;
45 | var limit = 5;
46 | var order = {
47 | test: [],
48 | iterator: []
49 | };
50 | var result = [];
51 | var test = function() {
52 | order.test.push(count);
53 | return count === limit;
54 | };
55 | var iterator = function(callback) {
56 | assert.strictEqual(this, undefined);
57 | result.push(count * count);
58 | order.iterator.push(count++);
59 | callback(null, count);
60 | };
61 |
62 | async.until(test, iterator, function(err, res) {
63 | if (err) {
64 | return done(err);
65 | }
66 | assert.deepStrictEqual(order.iterator, [0, 1, 2, 3, 4]);
67 | assert.deepStrictEqual(order.test, [0, 1, 2, 3, 4, 5]);
68 | assert.deepStrictEqual(result, [0, 1, 4, 9, 16]);
69 | assert.strictEqual(res, 5);
70 | done();
71 | }, Math);
72 | });
73 |
74 | it('should execute on asynchronous', function(done) {
75 |
76 | var sync = true;
77 | var count = 0;
78 | var limit = 5;
79 | var test = function() {
80 | return count === limit;
81 | };
82 | var iterator = function(callback) {
83 | count++;
84 | callback();
85 | };
86 | async.until(test, iterator, function(err) {
87 | if (err) {
88 | return done(err);
89 | }
90 | assert.strictEqual(sync, false);
91 | done();
92 | });
93 | sync = false;
94 | });
95 |
96 | it('should execute callback immediately if first test is truthy', function(done) {
97 |
98 | var test = function() {
99 | return true;
100 | };
101 | var iterator = function(callback) {
102 | callback();
103 | };
104 | async.until(test, iterator, done);
105 | });
106 |
107 | it('should get multiple result', function(done) {
108 |
109 | var count = 0;
110 | var limit = 5;
111 | var test = function() {
112 | assert.strictEqual(arguments.length, count);
113 | return count === limit;
114 | };
115 | var iterator = function(callback) {
116 | callback.apply(null, [null].concat(_.range(++count)));
117 | };
118 | async.until(test, iterator, function(err, res1, res2, res3, res4) {
119 | if (err) {
120 | return done(err);
121 | }
122 | assert.strictEqual(count, 5);
123 | assert.strictEqual(arguments.length, 6);
124 | assert.strictEqual(res1, 0);
125 | assert.strictEqual(res2, 1);
126 | assert.strictEqual(res3, 2);
127 | assert.strictEqual(res4, 3);
128 | done();
129 | });
130 | });
131 |
132 | it('should throw error', function(done) {
133 |
134 | var count = 0;
135 | var limit = 5;
136 | var order = {
137 | test: [],
138 | iterator: []
139 | };
140 | var test = function() {
141 | order.test.push(count);
142 | return count === limit;
143 | };
144 | var iterator = function(callback) {
145 | order.iterator.push(count++);
146 | callback(count === 3);
147 | };
148 | async.until(test, iterator, function(err) {
149 | assert.ok(err);
150 | assert.deepStrictEqual(order.iterator, [0, 1, 2]);
151 | assert.deepStrictEqual(order.test, [0, 1, 2]);
152 | done();
153 | });
154 | });
155 |
156 | });
157 |
158 | parallel('#doUntil', function() {
159 |
160 | it('should execute until test is false', function(done) {
161 |
162 | var count = 0;
163 | var limit = 5;
164 | var order = {
165 | test: [],
166 | iterator: []
167 | };
168 | var test = function() {
169 | order.test.push(count);
170 | return count === limit;
171 | };
172 | var iterator = function(callback) {
173 | order.iterator.push(count++);
174 | callback(null, count);
175 | };
176 |
177 | async.doUntil(iterator, test, function(err, res) {
178 | if (err) {
179 | return done(err);
180 | }
181 | assert.deepStrictEqual(order.iterator, [0, 1, 2, 3, 4]);
182 | assert.deepStrictEqual(order.test, [1, 2, 3, 4, 5]);
183 | assert.strictEqual(res, 5);
184 | done();
185 | });
186 | });
187 |
188 | it('should execute without binding until test is false', function(done) {
189 |
190 | var count = 0;
191 | var limit = 5;
192 | var order = {
193 | test: [],
194 | iterator: []
195 | };
196 | var result = [];
197 | var test = function() {
198 | order.test.push(count);
199 | return count === limit;
200 | };
201 | var iterator = function(callback) {
202 | assert.strictEqual(this, undefined);
203 | result.push(count * count);
204 | order.iterator.push(count++);
205 | callback(null, count);
206 | };
207 |
208 | async.doUntil(iterator, test, function(err, res) {
209 | if (err) {
210 | return done(err);
211 | }
212 | assert.deepStrictEqual(order.iterator, [0, 1, 2, 3, 4]);
213 | assert.deepStrictEqual(order.test, [1, 2, 3, 4, 5]);
214 | assert.deepStrictEqual(result, [0, 1, 4, 9, 16]);
215 | assert.strictEqual(res, 5);
216 | done();
217 | }, Math);
218 | });
219 |
220 | it('should execute until test is false and apply params', function(done) {
221 |
222 | var count = 0;
223 | var limit = 5;
224 | var order = {
225 | test: [],
226 | iterator: []
227 | };
228 | var test = function(c) {
229 | order.test.push(c);
230 | return c < limit;
231 | };
232 | var iterator = function(callback) {
233 | order.iterator.push(count++);
234 | callback(null, count);
235 | };
236 |
237 | async.doWhilst(iterator, test, function(err) {
238 | if (err) {
239 | return done(err);
240 | }
241 | assert.deepStrictEqual(order.iterator, [0, 1, 2, 3, 4]);
242 | assert.deepStrictEqual(order.test, [1, 2, 3, 4, 5]);
243 | done();
244 | });
245 |
246 | });
247 |
248 | it('should execute on asynchronous', function(done) {
249 |
250 | var sync = true;
251 | var count = 0;
252 | var limit = 5;
253 | var test = function() {
254 | return count === limit;
255 | };
256 | var iterator = function(callback) {
257 | count++;
258 | callback();
259 | };
260 | async.doUntil(iterator, test, function(err) {
261 | if (err) {
262 | return done(err);
263 | }
264 | assert.strictEqual(sync, false);
265 | done();
266 | });
267 | sync = false;
268 | });
269 |
270 | it('should get multiple result', function(done) {
271 |
272 | var count = 0;
273 | var limit = 5;
274 | var test = function(arg) {
275 | assert.strictEqual(arg, 0);
276 | assert.strictEqual(arguments.length, count);
277 | return count === limit;
278 | };
279 | var iterator = function(callback) {
280 | callback.apply(null, [null].concat(_.range(++count)));
281 | };
282 | async.doUntil(iterator, test, function(err, res1, res2, res3, res4) {
283 | if (err) {
284 | return done(err);
285 | }
286 | assert.strictEqual(count, 5);
287 | assert.strictEqual(arguments.length, 6);
288 | assert.strictEqual(res1, 0);
289 | assert.strictEqual(res2, 1);
290 | assert.strictEqual(res3, 2);
291 | assert.strictEqual(res4, 3);
292 | done();
293 | });
294 | });
295 |
296 | it('should throw error', function(done) {
297 |
298 | var count = 0;
299 | var limit = 5;
300 | var order = {
301 | test: [],
302 | iterator: []
303 | };
304 | var test = function() {
305 | order.test.push(count);
306 | return count === limit;
307 | };
308 | var iterator = function(callback) {
309 | order.iterator.push(count++);
310 | callback(count === 3);
311 | };
312 |
313 | async.doUntil(iterator, test, function(err) {
314 | assert.ok(err);
315 | assert.deepStrictEqual(order.iterator, [0, 1, 2]);
316 | assert.deepStrictEqual(order.test, [1, 2]);
317 | done();
318 | });
319 | });
320 |
321 | });
322 |
--------------------------------------------------------------------------------
/test/controlFlow/test.waterfall.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 | var domain = require('domain');
6 |
7 | var _ = require('lodash');
8 | var parallel = require('mocha.parallel');
9 |
10 | var async = global.async || require('../../');
11 | var delay = require('../config').delay;
12 | var util = require('../util');
13 |
14 | function createTasks(type, numbers) {
15 |
16 | switch (type) {
17 | case 'simple':
18 | return createSimpleTasks();
19 | case 'complex':
20 | return createComplexTasks();
21 | }
22 |
23 | function createSimpleTasks() {
24 |
25 | var first = true;
26 | var tasks = _.transform(numbers, function(memo, num, key) {
27 | if (first) {
28 | first = false;
29 | memo[key] = function(done) {
30 | if (this === Math) {
31 | num *= 2;
32 | }
33 | done(null, num);
34 | };
35 | } else {
36 | memo[key] = function(sum, done) {
37 | if (this === Math) {
38 | num *= 2;
39 | }
40 | done(null, sum + num);
41 | };
42 | }
43 | });
44 | return tasks;
45 | }
46 |
47 | function createComplexTasks() {
48 |
49 | var count = 0;
50 | var tasks = _.transform(numbers, function(memo, num, key) {
51 | if (count++ === 0) {
52 | memo[key] = function(done) {
53 | if (this === Math) {
54 | num *= 2;
55 | }
56 | done(null, num);
57 | };
58 | } else {
59 | memo[key] = function() {
60 | if (this === Math) {
61 | num *= 2;
62 | }
63 | var args = _.toArray(arguments);
64 | var done = args.pop();
65 | args.unshift(null);
66 | args.push(num);
67 | done.apply(null, args);
68 | };
69 | }
70 | });
71 | return tasks;
72 | }
73 |
74 | }
75 |
76 | parallel('#waterfall', function() {
77 |
78 | it('should execute to waterfall by collection of array', function(done) {
79 |
80 | var numbers = [1, 3, 2, 4];
81 | var tasks = createTasks('simple', numbers);
82 | async.waterfall(tasks, function(err, res) {
83 | if (err) {
84 | return done(err);
85 | }
86 | assert.strictEqual(res, 10);
87 | done();
88 | });
89 | });
90 |
91 | it('should execute simple tasks', function(done) {
92 |
93 | var numbers = [1, 3, 2, 4, 7, 8, 6, 5];
94 | var tasks = createTasks('simple', numbers);
95 | async.waterfall(tasks, function(err, result) {
96 | if (err) {
97 | return done(err);
98 | }
99 | assert.strictEqual(result, 36);
100 | done();
101 | });
102 | });
103 |
104 | it('should execute complex tasks', function(done) {
105 |
106 | var numbers = [1, 3, 2, 4, 7, 8, 6, 5];
107 | var tasks = createTasks('complex', numbers);
108 | async.waterfall(tasks, function(err, a, b, c, d, e, f, g, h) {
109 | if (err) {
110 | return done(err);
111 | }
112 | assert.strictEqual(a, 1);
113 | assert.strictEqual(b, 3);
114 | assert.strictEqual(c, 2);
115 | assert.strictEqual(d, 4);
116 |
117 | assert.strictEqual(e, 7);
118 | assert.strictEqual(f, 8);
119 | assert.strictEqual(g, 6);
120 | assert.strictEqual(h, 5);
121 |
122 | done();
123 | });
124 | });
125 |
126 | it('should throw error', function(done) {
127 |
128 | var numbers = [1, 3, 2, 4];
129 | var tasks = createTasks('simple', numbers);
130 | var errorTask = function(res, next) {
131 | next('error');
132 | };
133 | tasks.splice(2, 0, errorTask);
134 |
135 | async.waterfall(tasks, function(err) {
136 | assert.ok(err);
137 | done();
138 | });
139 | });
140 |
141 | it('should throw error if callback is called twice', function(done) {
142 |
143 | var errorCallCount = 0;
144 | setTimeout(function() {
145 | assert.strictEqual(errorCallCount, 1);
146 | done();
147 | }, delay);
148 |
149 | domain.create()
150 | .on('error', util.errorChecker)
151 | .on('error', function() {
152 | errorCallCount++;
153 | })
154 | .run(function() {
155 | var array = [
156 | function(next) {
157 | setImmediate(function() {
158 | next(null, 'one', 'two');
159 | });
160 | setImmediate(function() {
161 | next(null, 'one', 'two');
162 | });
163 | },
164 |
165 | function(arg1, arg2, next) {
166 | next(null, arg1, arg2, 'three');
167 | },
168 |
169 | function(arg1, arg2, arg3, next) {
170 | next(null, 'four');
171 | },
172 |
173 | function(arg1, next) {
174 | next();
175 | }
176 | ];
177 | async.waterfall(array);
178 | });
179 | });
180 |
181 | it('should throw error if task is not collection', function(done) {
182 |
183 | async.waterfall(null, function(err) {
184 | assert.strictEqual(err.message, 'First argument to waterfall must be an array of functions');
185 | done();
186 | });
187 | });
188 |
189 | it('should throw error with binding', function(done) {
190 |
191 | var numbers = [1, 3, 2, 4];
192 | var tasks = createTasks('simple', numbers);
193 | var errorTask = function(res, next) {
194 | next('error');
195 | };
196 | tasks.splice(2, 0, errorTask);
197 |
198 | async.waterfall(tasks, function(err) {
199 | assert.ok(err);
200 | done();
201 | }, Math);
202 | });
203 |
204 | it('should avoid double callback', function(done) {
205 |
206 | var called = false;
207 | var tasks = _.times(3, function(n) {
208 | return function(callback) {
209 | try {
210 | callback('error' + n);
211 | } catch (exception) {
212 | try {
213 | callback(exception);
214 | } catch(e) {
215 | assert.ok(e);
216 | util.errorChecker(e);
217 | }
218 | done();
219 | }
220 | };
221 | });
222 | async.waterfall(tasks, function(err) {
223 | assert.ok(err);
224 | assert.strictEqual(called, false);
225 | called = true;
226 | async.nothing();
227 | });
228 | });
229 |
230 | it('should return response immediately if array task is empty', function(done) {
231 |
232 | var tasks = [];
233 | async.waterfall(tasks, function(err, res) {
234 | if (err) {
235 | return done(err);
236 | }
237 | assert.strictEqual(res, undefined);
238 | done();
239 | });
240 | });
241 |
242 | it('multiple callback calls (trickier) @nodeonly', function(done) {
243 |
244 | var errorCallCount = 0;
245 | setTimeout(function() {
246 | assert.strictEqual(errorCallCount, 1);
247 | done();
248 | }, delay);
249 |
250 | domain.create()
251 | .on('error', util.errorChecker)
252 | .on('error', function() {
253 | errorCallCount++;
254 | })
255 | .run(function() {
256 | async.waterfall([
257 | function(callback) {
258 | setTimeout(callback, 0, null, 'one', 'two');
259 | setTimeout(callback, 10, null, 'one', 'two');
260 | },
261 | function(arg1, arg2, callback) {
262 | setTimeout(callback, 15, null, arg1, arg2, 'three');
263 | }
264 | ], function () {
265 | throw new Error('should not get here');
266 | });
267 | });
268 | });
269 |
270 | });
271 |
--------------------------------------------------------------------------------
/test/controlFlow/test.whilst.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var _ = require('lodash');
7 | var parallel = require('mocha.parallel');
8 |
9 | var async = global.async || require('../../');
10 | var delay = require('../config').delay;
11 |
12 | parallel('#whilst', function() {
13 |
14 | it('should execute until test is false', function(done) {
15 |
16 | var count = 0;
17 | var limit = 5;
18 | var order = {
19 | test: [],
20 | iterator: []
21 | };
22 | var test = function() {
23 | order.test.push(count);
24 | return count < limit;
25 | };
26 | var iterator = function(callback) {
27 | order.iterator.push(count++);
28 | callback(null, count);
29 | };
30 |
31 | async.whilst(test, iterator, function(err, res) {
32 | if (err) {
33 | return done(err);
34 | }
35 |
36 | assert.deepStrictEqual(order.iterator, [0, 1, 2, 3, 4]);
37 | assert.deepStrictEqual(order.test, [0, 1, 2, 3, 4, 5]);
38 | assert.strictEqual(res, 5);
39 | done();
40 | });
41 | });
42 |
43 | it('should execute without binding until test is false', function(done) {
44 |
45 | var count = 0;
46 | var limit = 5;
47 | var order = {
48 | test: [],
49 | iterator: []
50 | };
51 | var result = [];
52 | var test = function() {
53 | order.test.push(count);
54 | return count < limit;
55 | };
56 | var iterator = function(callback) {
57 | assert.strictEqual(this, undefined);
58 | result.push(count * count);
59 | order.iterator.push(count++);
60 | callback(null, count);
61 | };
62 |
63 | async.whilst(test, iterator, function(err, res) {
64 | if (err) {
65 | return done(err);
66 | }
67 |
68 | assert.deepStrictEqual(order.iterator, [0, 1, 2, 3, 4]);
69 | assert.deepStrictEqual(order.test, [0, 1, 2, 3, 4, 5]);
70 | assert.deepStrictEqual(result, [0, 1, 4, 9, 16]);
71 | assert.strictEqual(res, 5);
72 | done();
73 | }, Math);
74 | });
75 |
76 | it('should execute on asynchronous', function(done) {
77 |
78 | var sync = true;
79 | var count = 0;
80 | var limit = 5;
81 | var test = function() {
82 | return count < limit;
83 | };
84 | var iterator = function(callback) {
85 | count++;
86 | callback(null, count);
87 | };
88 | async.whilst(test, iterator, function(err, res) {
89 | if (err) {
90 | return done(err);
91 | }
92 | assert.strictEqual(sync, false);
93 | assert.strictEqual(res, 5);
94 | done();
95 | });
96 | sync = false;
97 | });
98 |
99 | it('should execute callback immediately if first test is falsy', function(done) {
100 |
101 | var test = function() {
102 | return false;
103 | };
104 | var iterator = function(callback) {
105 | callback();
106 | };
107 | async.whilst(test, iterator, done);
108 | });
109 |
110 | it('should get multiple result', function(done) {
111 |
112 | var count = 0;
113 | var limit = 5;
114 | var test = function() {
115 | assert.strictEqual(arguments.length, count);
116 | return count < limit;
117 | };
118 | var iterator = function(callback) {
119 | callback.apply(null, [null].concat(_.range(++count)));
120 | };
121 | async.whilst(test, iterator, function(err, res1, res2, res3, res4) {
122 | if (err) {
123 | return done(err);
124 | }
125 | assert.strictEqual(count, 5);
126 | assert.strictEqual(arguments.length, 6);
127 | assert.strictEqual(res1, 0);
128 | assert.strictEqual(res2, 1);
129 | assert.strictEqual(res3, 2);
130 | assert.strictEqual(res4, 3);
131 | done();
132 | });
133 | });
134 |
135 | it('should execute without callback', function(done) {
136 | var count = 0;
137 | var limit = 5;
138 | var test = function() {
139 | return count < limit;
140 | };
141 | var iterator = function(callback) {
142 | count++;
143 | callback();
144 | };
145 | async.whilst(test, iterator);
146 | setTimeout(function() {
147 | assert.strictEqual(count, 5);
148 | done();
149 | }, delay);
150 | });
151 |
152 | it('should throw error', function(done) {
153 |
154 | var count = 0;
155 | var limit = 5;
156 | var order = {
157 | test: [],
158 | iterator: []
159 | };
160 | var result = [];
161 | var test = function() {
162 | order.test.push(count);
163 | return count < limit;
164 | };
165 | var iterator = function(callback) {
166 | assert.strictEqual(this, undefined);
167 | result.push(count * count);
168 | order.iterator.push(count++);
169 | callback(count === 3);
170 | };
171 |
172 | async.whilst(test, iterator, function(err) {
173 | assert.ok(err);
174 | assert.deepStrictEqual(order.iterator, [0, 1, 2]);
175 | assert.deepStrictEqual(order.test, [0, 1, 2]);
176 | assert.deepStrictEqual(result, [0, 1, 4]);
177 | done();
178 | }, Math);
179 | });
180 |
181 | });
182 |
183 | parallel('#doWhilst', function() {
184 |
185 | it('should execute until test is false', function(done) {
186 |
187 | var count = 0;
188 | var limit = 5;
189 | var order = {
190 | test: [],
191 | iterator: []
192 | };
193 | var test = function() {
194 | order.test.push(count);
195 | return count < limit;
196 | };
197 | var iterator = function(callback) {
198 | order.iterator.push(count++);
199 | callback(null, count);
200 | };
201 |
202 | async.doWhilst(iterator, test, function(err, res) {
203 | if (err) {
204 | return done(err);
205 | }
206 | assert.deepStrictEqual(order.iterator, [0, 1, 2, 3, 4]);
207 | assert.deepStrictEqual(order.test, [1, 2, 3, 4, 5]);
208 | assert.strictEqual(res, 5);
209 | done();
210 | });
211 | });
212 |
213 | it('should execute without binding until test is false', function(done) {
214 |
215 | var count = 0;
216 | var limit = 5;
217 | var order = {
218 | test: [],
219 | iterator: []
220 | };
221 | var result = [];
222 | var test = function() {
223 | order.test.push(count);
224 | return count < limit;
225 | };
226 | var iterator = function(callback) {
227 | assert.strictEqual(this, undefined);
228 | result.push(count * count);
229 | order.iterator.push(count++);
230 | callback(null, count);
231 | };
232 |
233 | async.doWhilst(iterator, test, function(err, res) {
234 | if (err) {
235 | return done(err);
236 | }
237 | assert.deepStrictEqual(order.iterator, [0, 1, 2, 3, 4]);
238 | assert.deepStrictEqual(order.test, [1, 2, 3, 4, 5]);
239 | assert.deepStrictEqual(result, [0, 1, 4, 9, 16]);
240 | assert.strictEqual(res, 5);
241 | done();
242 | }, Math);
243 | });
244 |
245 | it('should execute until test is false and apply params', function(done) {
246 |
247 | var count = 0;
248 | var limit = 5;
249 | var order = {
250 | test: [],
251 | iterator: []
252 | };
253 | var test = function(c) {
254 | order.test.push(c);
255 | return c < limit;
256 | };
257 | var iterator = function(callback) {
258 | order.iterator.push(count++);
259 | callback(null, count);
260 | };
261 |
262 | async.doWhilst(iterator, test, function(err, res) {
263 | if (err) {
264 | return done(err);
265 | }
266 | assert.deepStrictEqual(order.iterator, [0, 1, 2, 3, 4]);
267 | assert.deepStrictEqual(order.test, [1, 2, 3, 4, 5]);
268 | assert.strictEqual(res, 5);
269 | done();
270 | });
271 | });
272 |
273 | it('should execute on asynchronous', function(done) {
274 |
275 | var sync = true;
276 | var count = 0;
277 | var limit = 5;
278 | var test = function() {
279 | return count < limit;
280 | };
281 | var iterator = function(callback) {
282 | count++;
283 | callback();
284 | };
285 | async.doWhilst(iterator, test, function(err) {
286 | if (err) {
287 | return done(err);
288 | }
289 | assert.strictEqual(sync, false);
290 | done();
291 | });
292 | sync = false;
293 | });
294 |
295 | it('should get multiple result', function(done) {
296 |
297 | var count = 0;
298 | var limit = 5;
299 | var test = function(arg) {
300 | assert.strictEqual(arg, 0);
301 | assert.strictEqual(arguments.length, count);
302 | return count < limit;
303 | };
304 | var iterator = function(callback) {
305 | callback.apply(null, [null].concat(_.range(++count)));
306 | };
307 | async.doWhilst(iterator, test, function(err, res1, res2, res3, res4) {
308 | if (err) {
309 | return done(err);
310 | }
311 | assert.strictEqual(count, 5);
312 | assert.strictEqual(arguments.length, 6);
313 | assert.strictEqual(res1, 0);
314 | assert.strictEqual(res2, 1);
315 | assert.strictEqual(res3, 2);
316 | assert.strictEqual(res4, 3);
317 | done();
318 | });
319 | });
320 |
321 | it('should execute without callback', function(done) {
322 | var count = 0;
323 | var limit = 5;
324 | var test = function() {
325 | return count < limit;
326 | };
327 | var iterator = function(callback) {
328 | count++;
329 | callback();
330 | };
331 | async.doWhilst(iterator, test);
332 | setTimeout(function() {
333 | assert.strictEqual(count, 5);
334 | done();
335 | }, delay);
336 | });
337 |
338 | it('should throw error', function(done) {
339 |
340 | var count = 0;
341 | var limit = 5;
342 | var order = {
343 | test: [],
344 | iterator: []
345 | };
346 | var result = [];
347 | var test = function() {
348 | order.test.push(count);
349 | return count < limit;
350 | };
351 | var iterator = function(callback) {
352 | assert.strictEqual(this, undefined);
353 | result.push(count * count);
354 | order.iterator.push(count++);
355 | callback(count === 3);
356 | };
357 |
358 | async.doWhilst(iterator, test, function(err) {
359 | assert.ok(err);
360 | assert.deepStrictEqual(order.iterator, [0, 1, 2]);
361 | assert.deepStrictEqual(order.test, [1, 2]);
362 | assert.deepStrictEqual(result, [0, 1, 4]);
363 | done();
364 | }, Math);
365 | });
366 |
367 | });
368 |
--------------------------------------------------------------------------------
/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --ui bdd
2 | --reporter spec
3 | --timeout 5000
4 |
--------------------------------------------------------------------------------
/test/other/test.alias.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = require('../../');
9 |
10 | parallel('#alias', function() {
11 |
12 | it('should have alias of forEach', function(done) {
13 |
14 | assert.strictEqual(async.forEach, async.each);
15 | done();
16 | });
17 |
18 | it('should have alias of forEachSeries', function(done) {
19 |
20 | assert.strictEqual(async.forEachSeries, async.eachSeries);
21 | done();
22 | });
23 |
24 | it('should have alias of forEachLimit', function(done) {
25 |
26 | assert.strictEqual(async.forEachLimit, async.eachLimit);
27 | done();
28 | });
29 |
30 | it('should have alias of eachOf', function(done) {
31 |
32 | assert.strictEqual(async.eachOf, async.each);
33 | done();
34 | });
35 |
36 | it('should have alias of eachOfSeries', function(done) {
37 |
38 | assert.strictEqual(async.eachOfSeries, async.eachSeries);
39 | done();
40 | });
41 |
42 | it('should have alias of eachLimit', function(done) {
43 |
44 | assert.strictEqual(async.eachOfLimit, async.eachLimit);
45 | done();
46 | });
47 |
48 | it('should have alias of forEachOf', function(done) {
49 |
50 | assert.strictEqual(async.forEachOf, async.each);
51 | done();
52 | });
53 |
54 | it('should have alias of forEachOfSeries', function(done) {
55 |
56 | assert.strictEqual(async.forEachOfSeries, async.eachSeries);
57 | done();
58 | });
59 |
60 | it('should have alias of forEachOfLimit', function(done) {
61 |
62 | assert.strictEqual(async.forEachOfLimit, async.eachLimit);
63 | done();
64 | });
65 |
66 | it('should have alias of inject', function(done) {
67 |
68 | assert.strictEqual(async.inject, async.reduce);
69 | done();
70 | });
71 |
72 | it('should have alias of foldl', function(done) {
73 |
74 | assert.strictEqual(async.foldl, async.reduce);
75 | done();
76 | });
77 |
78 | it('should have alias of foldr', function(done) {
79 |
80 | assert.strictEqual(async.foldr, async.reduceRight);
81 | done();
82 | });
83 |
84 | it('should have alias of any', function(done) {
85 |
86 | assert.strictEqual(async.any, async.some);
87 | done();
88 | });
89 |
90 | it('should have alias of all', function(done) {
91 |
92 | assert.strictEqual(async.all, async.every);
93 | done();
94 | });
95 |
96 | it('should have alias of angelfall', function(done) {
97 |
98 | assert.strictEqual(async.angelfall, async.angelFall);
99 | done();
100 | });
101 |
102 | it('should have alias of wrapSync', function(done) {
103 |
104 | assert.strictEqual(async.wrapSync, async.asyncify);
105 | done();
106 | });
107 | });
108 |
--------------------------------------------------------------------------------
/test/other/test.other.js:
--------------------------------------------------------------------------------
1 | /* global it, before, after */
2 |
3 | var fs = require('fs');
4 | var vm = require('vm');
5 | var path = require('path');
6 | var assert = require('assert');
7 |
8 | var _ = require('lodash');
9 | var parallel = require('mocha.parallel');
10 |
11 | var async = global.async || require('../../');
12 | var asyncPath = global.async_path || path.resolve(__dirname, '../../lib/async.js');
13 |
14 | parallel('#nextTick', function() {
15 |
16 | 'use strict';
17 |
18 | it('should assign setImmediate when process does not exist', function(done) {
19 |
20 | var context = {
21 | require: require,
22 | console: console,
23 | exports: exports,
24 | setTimeout: setTimeout,
25 | setImmediate: setImmediate
26 | };
27 | vm.runInNewContext(fs.readFileSync(asyncPath), context);
28 | assert.strictEqual(typeof context.async.nextTick, 'function');
29 | assert.notStrictEqual(context.async.nextTick, process.nextTick);
30 | assert.strictEqual(context.async.nextTick, setImmediate);
31 | context.async.nextTick(done);
32 | });
33 |
34 | it('should assign setImmediate when process does not exist for coverage', function(done) {
35 |
36 | var _nextTick = process.nextTick;
37 | process.nextTick = undefined;
38 | delete(require.cache[asyncPath]);
39 | var async = require(asyncPath);
40 | process.nextTick = _nextTick;
41 | assert.strictEqual(typeof async.nextTick, 'function');
42 | assert.notStrictEqual(async.nextTick, process.nextTick);
43 | assert.strictEqual(async.nextTick, setImmediate);
44 | async.nextTick(done);
45 | });
46 |
47 | it('should create original nextTick when process does not have nextTick and setImmediate', function(done) {
48 |
49 | var context = {
50 | require: require,
51 | console: console,
52 | exports: exports,
53 | setTimeout: setTimeout
54 | };
55 | vm.runInNewContext(fs.readFileSync(asyncPath), context);
56 | assert.strictEqual(typeof context.async.nextTick, 'function');
57 | assert.notStrictEqual(context.async.nextTick, process.nextTick);
58 | context.async.nextTick(done);
59 | });
60 |
61 | it('should create original nextTick when process does not have nextTick and setImmediate for coverage', function(done) {
62 |
63 | var _nextTick = process.nextTick;
64 | var _setImmediate = setImmediate;
65 | process.nextTick = undefined;
66 | setImmediate = undefined;
67 | delete(require.cache[asyncPath]);
68 | var async = require(asyncPath);
69 | process.nextTick = _nextTick;
70 | setImmediate = _setImmediate;
71 | assert.strictEqual(typeof async.nextTick, 'function');
72 | assert.notStrictEqual(async.nextTick, process.nextTick);
73 | async.nextTick(done);
74 | });
75 |
76 | it('should avoid node warning [v0.10.x only]', function(done) {
77 |
78 | var array = _.times(10000);
79 | var iterator = function(n, done) {
80 | done();
81 | };
82 | async.eachSeries(array, iterator, done);
83 | });
84 |
85 | it('should pass extra arguments', function(done) {
86 |
87 | async.nextTick(function(a, b, c, d) {
88 | assert.strictEqual(a, 1);
89 | assert.strictEqual(b, 2);
90 | assert.strictEqual(c, 3);
91 | assert.strictEqual(d, undefined);
92 | done();
93 | }, 1, 2, 3);
94 | });
95 | });
96 |
97 | parallel('#setImmediate', function() {
98 |
99 | 'use strict';
100 |
101 | it('should create original setImmediate if does not have setImmediate', function(done) {
102 |
103 | var context = {
104 | require: require,
105 | console: console,
106 | exports: exports,
107 | setTimeout: setTimeout
108 | };
109 | vm.runInNewContext(fs.readFileSync(asyncPath), context);
110 | assert.strictEqual(typeof context.async.nextTick, 'function');
111 | assert.notStrictEqual(context.async.nextTick, process.nextTick);
112 | context.async.nextTick(done);
113 | });
114 |
115 | it('should create original setImmediate if does not have setImmediate for coverage', function(done) {
116 |
117 | var _setImmediate = setImmediate;
118 | setImmediate = undefined;
119 | delete(require.cache[asyncPath]);
120 | var async = require(asyncPath);
121 | setImmediate = _setImmediate;
122 | assert.strictEqual(typeof async.setImmediate, 'function');
123 | assert.notStrictEqual(async.setImmediate, process.nextTick);
124 | async.nextTick(done);
125 | });
126 |
127 | it('should pass extra arguments', function(done) {
128 |
129 | var _setImmediate = setImmediate;
130 | setImmediate = undefined;
131 | delete(require.cache[asyncPath]);
132 | var async = require(asyncPath);
133 | setImmediate = _setImmediate;
134 | async.setImmediate(function(a, b, c, d) {
135 | assert.strictEqual(a, 1);
136 | assert.strictEqual(b, 2);
137 | assert.strictEqual(c, 3);
138 | assert.strictEqual(d, undefined);
139 | done();
140 | }, 1, 2, 3);
141 | });
142 | });
143 |
144 | parallel('#check functions', function() {
145 |
146 | 'use strict';
147 |
148 | it('should have async functions', function() {
149 | _.forOwn(require('async'), function(func, key) {
150 | assert.ok(async[key], key + ' wasn\'t found.');
151 | });
152 | });
153 | });
154 |
155 | parallel('#other', function() {
156 |
157 | 'use strict';
158 |
159 | var path = require('path');
160 |
161 | it('should check whether "async" is assigned to context', function() {
162 |
163 | var context = {
164 | require: require,
165 | console: console,
166 | exports: exports
167 | };
168 | vm.runInNewContext(fs.readFileSync(path.resolve(__dirname, '../../lib/async.js')), context);
169 | assert.ok(context.async);
170 | _.forOwn(context.async, function(func, key) {
171 | assert.ok(async[key]);
172 | });
173 | });
174 |
175 | it('should check whether "neo_async" is assigned to context', function() {
176 |
177 | var context = {
178 | require: require,
179 | console: console,
180 | exports: exports,
181 | async: require('async')
182 | };
183 | vm.runInNewContext(fs.readFileSync(path.resolve(__dirname, '../../lib/async.js')), context);
184 | assert.ok(context.neo_async);
185 | _.forOwn(context.neo_async, function(func, key) {
186 | assert.ok(async[key]);
187 | });
188 | });
189 | });
190 |
191 | parallel('#default', function() {
192 |
193 | 'use strict';
194 |
195 | it('should have same functions', function() {
196 |
197 | _.forOwn(async['default'], function(value, key) {
198 | assert.ok(async[key], key + ' wasn\'t found.');
199 | });
200 | });
201 | });
202 |
203 | parallel('#safe', function() {
204 |
205 | 'use strict';
206 |
207 | it('should execute on asynchronous', function(done) {
208 |
209 | async.safe();
210 | var sync = true;
211 | var collection = [1, 3, 2];
212 | var iterator = function(value, key, callback) {
213 | // sync call
214 | callback();
215 | };
216 |
217 | async.eachSeries(collection, iterator, function(err) {
218 | if (err) {
219 | return done(err);
220 | }
221 | assert.strictEqual(sync, false);
222 | done();
223 | });
224 | sync = false;
225 | });
226 | });
227 |
228 | parallel('#fast', function() {
229 |
230 | 'use strict';
231 |
232 | before(function() {
233 | async.fast();
234 | });
235 |
236 | after(function() {
237 | async.safe();
238 | });
239 |
240 | it('should execute on synchronous', function(done) {
241 |
242 | var sync = true;
243 | var collection = [1, 3, 2];
244 | var iterator = function(value, key, callback) {
245 | // sync call
246 | callback();
247 | };
248 |
249 | async.eachSeries(collection, iterator, function(err) {
250 | if (err) {
251 | return done(err);
252 | }
253 | assert.strictEqual(sync, true);
254 | done();
255 | });
256 | sync = false;
257 | });
258 | });
259 |
--------------------------------------------------------------------------------
/test/util.js:
--------------------------------------------------------------------------------
1 | /* global it, Map, Set, Promise */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var _it = typeof Symbol === 'function' ? it : it.skip;
7 | _it.only =
8 | _it.only ||
9 | function skipOnly(key) {
10 | it.only(key);
11 | };
12 |
13 | exports.it = _it;
14 |
15 | /**
16 | * for v0.10.x
17 | */
18 | exports.Map =
19 | typeof Map === 'function'
20 | ? Map
21 | : (function() {
22 | function Map(arr) {
23 | this._data = arr || [];
24 | }
25 | Map.prototype.set = function(key, value) {
26 | this._data.push([key, value]);
27 | };
28 | Map.prototype[global.Symbol.iterator] = function() {
29 | var self = this;
30 | return {
31 | next: function() {
32 | var data = self._data.shift();
33 | return {
34 | value: data,
35 | done: data === undefined
36 | };
37 | }
38 | };
39 | };
40 | Object.defineProperty(Map.prototype, 'size', {
41 | get: function() {
42 | return this._data.length;
43 | }
44 | });
45 | return Map;
46 | })();
47 |
48 | exports.Set =
49 | typeof Set === 'function'
50 | ? Set
51 | : (function() {
52 | function Set(arr) {
53 | this._data = arr || [];
54 | }
55 | Set.prototype.add = function(value) {
56 | this._data.push(value);
57 | };
58 | Set.prototype[global.Symbol.iterator] = function() {
59 | var self = this;
60 | return {
61 | next: function() {
62 | var data = self._data.shift();
63 | return {
64 | value: data,
65 | done: data === undefined
66 | };
67 | }
68 | };
69 | };
70 | Object.defineProperty(Set.prototype, 'size', {
71 | get: function() {
72 | return this._data.length;
73 | }
74 | });
75 | return Set;
76 | })();
77 |
78 | exports.errorChecker = function(err) {
79 | assert.ok(err);
80 | assert.strictEqual(err.message, 'Callback was already called.');
81 | };
82 |
83 | exports.uncaughtExceptionHandler = function(func) {
84 | var handler = function(err) {
85 | func(err);
86 | process.removeListener('uncaughtException', handler);
87 | };
88 | process.removeAllListeners('uncaughtException');
89 | process.domain = null;
90 | process.on('uncaughtException', handler);
91 | };
92 |
93 | exports.Promise = typeof Promise !== 'undefined' ? Promise : require('bluebird');
94 |
95 | exports.makeGenerator = function*(arr) {
96 | var idx = 0;
97 | var len = arr.length;
98 | while (idx < len) {
99 | yield arr[idx++];
100 | }
101 | };
102 |
--------------------------------------------------------------------------------
/test/utils/test.asyncify.js:
--------------------------------------------------------------------------------
1 | /* global it, describe */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var async = require('../../');
7 | var delay = require('../config').delay;
8 | var util = require('../util');
9 |
10 | describe('#asyncify', function() {
11 |
12 | it('should call a synchronous function asynchronously', function(done) {
13 |
14 | var test = {
15 | hoge: true
16 | };
17 | var func = function() {
18 | return test;
19 | };
20 | async.asyncify(func)(function(err, res) {
21 | if (err) {
22 | return done(err);
23 | }
24 | assert.strictEqual(res, test);
25 | done();
26 | });
27 | });
28 |
29 | it('should call a synchronous function which has a promise as a result', function(done) {
30 |
31 | var test = {
32 | hoge: true
33 | };
34 | var func = function() {
35 | return util.Promise.resolve(test);
36 | };
37 | async.asyncify(func)(function(err, res) {
38 | if (err) {
39 | return done(err);
40 | }
41 | assert.strictEqual(res, test);
42 | done();
43 | });
44 | });
45 |
46 | it('should throw error', function(done) {
47 |
48 | var message = 'error';
49 | var func = function() {
50 | throw new Error(message);
51 | };
52 | async.asyncify(func)(function(err) {
53 | assert.ok(err);
54 | assert.strictEqual(err.message, message);
55 | done();
56 | });
57 | });
58 |
59 | it('should throw error by promise', function(done) {
60 |
61 | var message = 'error';
62 | var func = function() {
63 | return util.Promise.reject(new Error(message));
64 | };
65 | async.asyncify(func)(function(err) {
66 | assert.ok(err);
67 | assert.strictEqual(err.message, message);
68 | done();
69 | });
70 | });
71 |
72 | it('should throw an uncaughtException instead of unhandledRejection', function(done) {
73 |
74 | var error = new Error('callback error');
75 | util.uncaughtExceptionHandler(function(err) {
76 | assert.ok(err);
77 | assert.strictEqual(err, error);
78 | done();
79 | });
80 | var func = function() {
81 | return util.Promise.reject(new Error('error'));
82 | };
83 | async.asyncify(func)(function(err) {
84 | assert.ok(err);
85 | throw error;
86 | });
87 | });
88 |
89 | it('should avoid TypeError if return object is null', function(done) {
90 |
91 | var func = function() {
92 | return null;
93 | };
94 | async.asyncify(func)(function(err, res) {
95 | if (err) {
96 | return done(err);
97 | }
98 | assert.strictEqual(res, null);
99 | done();
100 | });
101 | });
102 |
103 | it('should throw an error if reject is called', function(done) {
104 |
105 | var func = function(arg) {
106 | return util.Promise.reject(arg + ' rejected');
107 | };
108 | async.asyncify(func)('argument', function(err) {
109 | assert.ok(err);
110 | assert.strictEqual(err.message, 'argument rejected');
111 | done();
112 | });
113 | });
114 |
115 | it('should throw an error even if reject is called with null', function(done) {
116 | var func = function() {
117 | return util.Promise.reject(null);
118 | };
119 | async.asyncify(func)(function(err) {
120 | assert.ok(err);
121 | assert.ok(err instanceof Error);
122 | assert.strictEqual(err.message, 'null');
123 | done();
124 | });
125 | });
126 |
127 | it('should avoid double callback', function(done) {
128 |
129 | var count = 0;
130 | var msg = 'error in callback';
131 | util.uncaughtExceptionHandler(function(err) {
132 | assert.ok(err);
133 | assert.strictEqual(err.message, msg);
134 | });
135 | var promisified = function(arg) {
136 | return new util.Promise(function(resolve) {
137 | resolve(arg + ' resolved');
138 | });
139 | };
140 | async.asyncify(promisified)('arg', function(err, res) {
141 | count++;
142 | if (err) {
143 | return done(err);
144 | }
145 | assert.strictEqual(res, 'arg resolved');
146 | setTimeout(function() {
147 | assert.strictEqual(count, 1);
148 | done();
149 | }, delay);
150 | throw new Error(msg);
151 | });
152 | });
153 | });
154 |
--------------------------------------------------------------------------------
/test/utils/test.constant.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = require('../../');
9 |
10 | parallel('#constant', function() {
11 |
12 | it('should get constant response', function(done) {
13 | async.constant(1, 2, 3)(function(err, result1, result2, result3) {
14 | if (err) {
15 | return done(err);
16 | }
17 | assert.deepStrictEqual(result1, 1);
18 | assert.deepStrictEqual(result2, 2);
19 | assert.deepStrictEqual(result3, 3);
20 | done();
21 | });
22 | });
23 |
24 | it('should ignore other arguments', function(done) {
25 | async.constant(1, 2, 3)(4, 5, 6, 7, function(err, result1, result2, result3) {
26 | if (err) {
27 | return done(err);
28 | }
29 | assert.deepStrictEqual(result1, 1);
30 | assert.deepStrictEqual(result2, 2);
31 | assert.deepStrictEqual(result3, 3);
32 | assert.strictEqual(arguments.length, 4);
33 | done();
34 | });
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/test/utils/test.createLogger.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = require('../../');
9 |
10 | parallel('#createLogger', function() {
11 |
12 | it('should test logger', function(done) {
13 |
14 | var fn = function(name) {
15 |
16 | return function(arg, callback) {
17 |
18 | assert.equal(arg, name);
19 | callback(null, name);
20 | };
21 | };
22 |
23 | var names = ['log', 'dir', 'test'];
24 | var name = names.shift();
25 | var logger = async.createLogger(name);
26 |
27 | logger(fn(name), name, function(err, res) {
28 | if (err) {
29 | return done(err);
30 | }
31 |
32 | assert.equal(res, 'log');
33 | name = names.shift();
34 | logger = async.createLogger(name);
35 |
36 | logger(fn(name), name, function(err, res) {
37 | if (err) {
38 | return done(err);
39 | }
40 |
41 | assert.equal(res, 'dir');
42 | name = names.shift();
43 | logger = async.createLogger(name);
44 |
45 | logger(fn(name), name, function(err, res) {
46 | if (err) {
47 | return done(err);
48 | }
49 |
50 | assert.equal(res, 'test');
51 | done();
52 | });
53 | });
54 | });
55 |
56 | });
57 |
58 | it('should throw error', function(done) {
59 |
60 | var fn = function(name) {
61 |
62 | return function(arg, done, logger) {
63 |
64 | assert.equal(arg, name);
65 | logger('error');
66 | done('error');
67 | };
68 | };
69 |
70 | var names = ['log', 'debug', 'info'];
71 | var name = names.shift();
72 | var logger = async.createLogger(name);
73 |
74 | logger(fn(name), name, function(err) {
75 | assert.ok(err);
76 | done();
77 | });
78 |
79 | });
80 |
81 | it('should check logger', function(done) {
82 |
83 | var fn = function(arg, callback) {
84 | assert.strictEqual(arg, 'test');
85 | callback(null, 'log', 'test');
86 | done();
87 | };
88 | var logger = async.createLogger('warn');
89 | logger(fn, 'test');
90 | });
91 |
92 | });
93 |
--------------------------------------------------------------------------------
/test/utils/test.ensureAsync.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = require('../../');
9 |
10 | parallel('#ensureAsync', function() {
11 |
12 | it('should call function on asynchronous even if funcion is called on synchronous', function(done) {
13 |
14 | var sync = true;
15 | var func = function(callback) {
16 | callback();
17 | };
18 | async.ensureAsync(func)(function(err) {
19 | if (err) {
20 | return done(err);
21 | }
22 | assert.strictEqual(sync, false);
23 | done();
24 | });
25 | sync = false;
26 | });
27 |
28 | it('should call asynchronous function', function(done) {
29 |
30 | var sync = true;
31 | var func = function(callback) {
32 | setImmediate(callback);
33 | };
34 | async.ensureAsync(func)(function(err) {
35 | if (err) {
36 | return done(err);
37 | }
38 | assert.strictEqual(sync, false);
39 | done();
40 | });
41 | sync = false;
42 | });
43 |
44 | it('should bind context', function(done) {
45 |
46 | var func = function(callback) {
47 | callback(this);
48 | };
49 | var newFunc = async.ensureAsync(func);
50 | newFunc = newFunc.bind(Math);
51 | newFunc(function(res) {
52 | assert.strictEqual(res, Math);
53 | done();
54 | });
55 | });
56 |
57 | it('should not override the bound context of function', function(done) {
58 |
59 | var func = function(callback) {
60 | callback(this);
61 | };
62 | var newFunc = func.bind(Math);
63 | newFunc = async.ensureAsync(newFunc);
64 | newFunc(function(res) {
65 | assert.strictEqual(res, Math);
66 | done();
67 | });
68 | });
69 | });
70 |
--------------------------------------------------------------------------------
/test/utils/test.memoize.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = require('../../');
9 |
10 | parallel('#memoize', function() {
11 |
12 | it('should callback memo if same arguments', function(done) {
13 |
14 | var order = [];
15 | var fn = function(arg, callback) {
16 | order.push(arg);
17 | callback();
18 | };
19 |
20 | var fn2 = async.memoize(fn);
21 |
22 | fn2(1, function() {
23 |
24 | fn2(2, function() {
25 |
26 | fn2(1, function() {
27 |
28 | assert.deepStrictEqual(order, [1, 2]);
29 | done();
30 | });
31 | });
32 | });
33 | });
34 |
35 | it('should callback memo and maintain asynchrony', function(done) {
36 |
37 | var order = [];
38 | var fn = function(arg1, arg2, callback) {
39 | order.push(['fn', arg1, arg2]);
40 | async.setImmediate(function() {
41 | order.push(['cb', arg1, arg2]);
42 | callback(null, arg1 + arg2);
43 | });
44 | };
45 |
46 | var fn2 = async.memoize(fn);
47 |
48 | fn2(1, 2, function(err, res) {
49 | assert.equal(res, 3);
50 | fn2(1, 2, function(err, res) {
51 | assert.equal(res, 3);
52 | async.nextTick(memoize_done);
53 | order.push('tick3');
54 | });
55 | order.push('tick2');
56 | });
57 | order.push('tick1');
58 |
59 | function memoize_done() {
60 |
61 | var call_order = [
62 | ['fn', 1, 2],
63 | 'tick1', ['cb', 1, 2],
64 | // ['fn', 1, 2], memoized
65 | 'tick2',
66 | // ['cb', 1, 2], memoized
67 | 'tick3'
68 | ];
69 | assert.deepStrictEqual(call_order, order);
70 | done();
71 | }
72 |
73 | });
74 |
75 | it('should use queue', function(done) {
76 |
77 | var order = [];
78 | var fn = function(arg, callback) {
79 | order.push(arg);
80 | setTimeout(function() {
81 | callback(null, arg);
82 | }, 100);
83 | };
84 |
85 | var fn2 = async.memoize(fn);
86 | fn2(1, function(err, res) {
87 | assert.ok(!err);
88 | assert.strictEqual(res, 1);
89 | });
90 | fn2(2, function(err, res) {
91 | assert.ok(!err);
92 | assert.strictEqual(res, 2);
93 | });
94 | fn2(1, function(err, res) {
95 | assert.ok(!err);
96 | assert.strictEqual(res, 1);
97 | });
98 | setTimeout(function() {
99 | assert.deepStrictEqual(order, [1, 2]);
100 | done();
101 | }, 300);
102 |
103 | });
104 |
105 | it('should not memoize result if error occurs', function(done) {
106 |
107 | var called = 0;
108 | var order = [];
109 | var error = new Error('error');
110 | var fn = function(arg, callback) {
111 | called++;
112 | callback(error, arg);
113 | };
114 | var memoized = async.memoize(fn);
115 | memoized(1, function(err) {
116 | assert.strictEqual(err, error);
117 | error = null;
118 | memoized(1, function(err, result) {
119 | assert.strictEqual(err, null);
120 | assert.strictEqual(result, 1);
121 | assert.strictEqual(called, 2);
122 | done();
123 | });
124 | })
125 | });
126 |
127 | });
128 |
--------------------------------------------------------------------------------
/test/utils/test.reflect.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = require('../../');
9 |
10 | parallel('#reflect', function() {
11 |
12 | it('should execute with error in parallel', function(done) {
13 |
14 | var tasks = [
15 | async.reflect(function(callback) {
16 | callback('error', 1);
17 | }),
18 | async.reflect(function(callback) {
19 | callback('error2', 2);
20 | }),
21 | async.reflect(function(callback) {
22 | callback(null, 3);
23 | })
24 | ];
25 | async.parallel(tasks, function(err, res) {
26 | if (err) {
27 | return done(err);
28 | }
29 | assert.deepStrictEqual(res, [
30 | { error: 'error' },
31 | { error: 'error2' },
32 | { value: 3 }
33 | ]);
34 | done();
35 | });
36 | });
37 |
38 | it('should execute with error in series', function(done) {
39 |
40 | var tasks = [
41 | async.reflect(function(callback) {
42 | callback('error', 1);
43 | }),
44 | async.reflect(function(callback) {
45 | callback('error2', 2);
46 | }),
47 | async.reflect(function(callback) {
48 | callback(null, 3, 3);
49 | })
50 | ];
51 | async.series(tasks, function(err, res) {
52 | if (err) {
53 | return done(err);
54 | }
55 | assert.deepStrictEqual(res, [
56 | { error: 'error' },
57 | { error: 'error2' },
58 | { value: [3, 3] }
59 | ]);
60 | done();
61 | });
62 | });
63 |
64 | it('should execute even if it has an argument', function(done) {
65 |
66 | var reflect = async.reflect(function(arg, callback) {
67 | callback('error', arg);
68 | });
69 | reflect(1, function(err, res) {
70 | if (err) {
71 | return done(err);
72 | }
73 | assert.deepStrictEqual(res, {
74 | error: 'error'
75 | });
76 | done();
77 | });
78 | });
79 |
80 | it('should execute even if it has two arguments', function(done) {
81 |
82 | var reflect = async.reflect(function(arg1, arg2, callback) {
83 | callback(null, arg1, arg2);
84 | });
85 | reflect(1, 2, function(err, res) {
86 | if (err) {
87 | return done(err);
88 | }
89 | assert.deepStrictEqual(res, {
90 | value: [1, 2]
91 | });
92 | done();
93 | });
94 | });
95 |
96 | it('should execute even if it has some arguments', function(done) {
97 |
98 | var reflect = async.reflect(function(arg1, arg2, arg3, arg4, callback) {
99 | callback(null, arg3, arg4, arg1);
100 | });
101 | reflect(1, 2, 3, 4, function(err, res) {
102 | if (err) {
103 | return done(err);
104 | }
105 | assert.deepStrictEqual(res, {
106 | value: [3, 4, 1]
107 | });
108 | done();
109 | });
110 | });
111 | });
112 |
113 | parallel('#reflectAll', function() {
114 |
115 | it('should execute array tasks', function(done) {
116 | var tasks = [
117 | function(done) {
118 | done('error', 1);
119 | },
120 | function(done) {
121 | done('error2', 2);
122 | },
123 | function(done) {
124 | done(null, 3);
125 | }
126 | ];
127 | async.parallel(async.reflectAll(tasks), function(err, res) {
128 | if (err) {
129 | return done(err);
130 | }
131 | assert.deepStrictEqual(res, [
132 | { error: 'error' },
133 | { error: 'error2' },
134 | { value: 3 }
135 | ]);
136 | done();
137 | });
138 | });
139 |
140 | it('should execute object tasks', function(done) {
141 | var tasks = {
142 | a: function(done) {
143 | done('error', 1);
144 | },
145 | b: function(done) {
146 | done('error2', 2);
147 | },
148 | c: function(done) {
149 | done(null, 3, 4, 5);
150 | }
151 | };
152 | async.parallel(async.reflectAll(tasks), function(err, res) {
153 | if (err) {
154 | return done(err);
155 | }
156 | assert.deepStrictEqual(res, {
157 | a: { error: 'error' },
158 | b: { error: 'error2' },
159 | c: { value: [3, 4, 5] }
160 | });
161 | done();
162 | });
163 | });
164 | });
165 |
--------------------------------------------------------------------------------
/test/utils/test.unmemoize.js:
--------------------------------------------------------------------------------
1 | /* global it */
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | var parallel = require('mocha.parallel');
7 |
8 | var async = require('../../');
9 |
10 | parallel('#unmemoize', function() {
11 |
12 | it('should execute without memo', function(done) {
13 |
14 | var order = [];
15 | var fn = function(arg, callback) {
16 | order.push(arg);
17 | callback();
18 | };
19 |
20 | var fn2 = async.memoize(fn);
21 | fn2 = async.unmemoize(fn2);
22 |
23 | fn2(1, function() {
24 |
25 | fn2(2, function() {
26 |
27 | fn2(1, function() {
28 |
29 | assert.deepStrictEqual(order, [1, 2, 1]);
30 | done();
31 | });
32 | });
33 | });
34 | });
35 |
36 | });
37 |
--------------------------------------------------------------------------------