1 | # fw [![Build Status](https://travis-ci.org/h2non/fw.svg?branch=master)][travis] [![NPM version](https://badge.fury.io/js/fw.svg)][npm]
|
2 |
|
3 | ## About
|
4 |
|
5 | **fw** is a tiny library which helps with **asynchronous
|
6 | control-flow management** in JavaScript environments
|
7 |
|
8 | It exploits **functional-style programming** using higher-order functions and other common patterns.
|
9 | You could use it in conjunction with [hu][hu], for a better approach
|
10 |
|
11 | ## Features
|
12 |
|
13 | - Support series or parallel control-flow modes
|
14 | - Collections iterators (each, map...)
|
15 | - Runs in node and browsers
|
16 | - Simple and easy-to-use API
|
17 | - Tiny (~200 SLOC)
|
18 | - Dependency-free
|
19 | - Designed to be embedded in libraries or applications
|
20 |
|
21 | ## Installation
|
22 |
|
23 | #### Node.js
|
24 |
|
25 | ```bash
|
26 | $ npm install fw --save
|
27 | ```
|
28 |
|
29 | #### Browser
|
30 |
|
31 | Via Bower package manager
|
32 | ```bash
|
33 | $ bower install fw
|
34 | ```
|
35 |
|
36 | Or loading the script remotely (just for testing or development)
|
37 | ```html
|
38 | <script src="//rawgithub.com/h2non/fw/master/fw.js"></script>
|
39 | ```
|
40 |
|
41 | ## Environments
|
42 |
|
43 | It works properly in any ES5 compliant engine
|
44 |
|
45 | - Node.js
|
46 | - Chrome >= 5
|
47 | - Firefox >= 3
|
48 | - Safari >= 5
|
49 | - Opera >= 12
|
50 | - IE >= 9
|
51 |
|
52 | ## API
|
53 |
|
54 | ```js
|
55 | var fw = require('fw')
|
56 | ```
|
57 |
|
58 | ### series(tasks, callback)
|
59 |
|
60 | Run the functions in the array in series (sequentially).
|
61 | Each function will be executed only if its previous function has completed
|
62 |
|
63 | If any functions in the series pass an error to its callback,
|
64 | no more functions are run and callback is immediately
|
65 | called with the value of the error
|
66 |
|
67 | ##### Arguments
|
68 |
|
69 | - **tasks** - An array containing functions to run. Each function is passed a `callback(err, result)`
|
70 | - **callback** - Optional callback to run once all the functions have completed.
|
71 | This function gets an array of results containing all the result arguments passed
|
72 | to the task callbacks. `undefined` or `null` values will be omitted from results
|
73 |
|
74 | ```js
|
75 | fw.series([
|
76 | function (next) {
|
77 | setTimeout(function () {
|
78 | next(null, 1)
|
79 | }, 100)
|
80 | },
|
81 | function (next, result) {
|
82 | setTimeout(function () {
|
83 | next(null, result + 1)
|
84 | }, 100)
|
85 | }
|
86 | ], function (err, results) {
|
87 | console.log(err) // → undefined
|
88 | console.log(results) // → [1, 2]
|
89 | })
|
90 | ```
|
91 |
|
92 | ### parallel(tasks, callback)
|
93 |
|
94 | Run the tasks array of functions in parallel, without waiting until the previous function has completed
|
95 |
|
96 | Once the `tasks` have completed, the results are passed to the final `callback` as an array
|
97 |
|
98 | ##### arguments
|
99 |
|
100 | - **tasks** - An array containing functions to run. Each function is passed a `callback(err, result)`
|
101 | - **callback** - Optional callback to run once all the functions have completed.
|
102 | This function gets an array of results containing all the result arguments passed
|
103 | to the task callbacks. `undefined` or `null` values will be omitted from results
|
104 |
|
105 | ```js
|
106 | fw.parallel([
|
107 | function (done) {
|
108 | setTimeout(function () {
|
109 | done(null, 1)
|
110 | }, 100)
|
111 | },
|
112 | function (done) {
|
113 | setTimeout(function () {
|
114 | done(null, 2)
|
115 | }, 150)
|
116 | }
|
117 | ], function (err, results) {
|
118 | console.log(err) // → undefined
|
119 | console.log(results) // → [1, 2]
|
120 | })
|
121 | ```
|
122 |
|
123 | ### whilst(test, fn, callback)
|
124 |
|
125 | Repeatedly call a function, while test returns true.
|
126 | Calls callback when stopped or an error occurs
|
127 |
|
128 | ##### arguments
|
129 |
|
130 | - **test()** - synchronous truth test to perform before each execution of fn.
|
131 | - **fn(callback)** - A function which is called each time test passes. The function is passed a `callback(err)`, which must be called once it has completed with an optional err argument
|
132 | - **callback(err)** - A callback which is called after the test fails and repeated execution of `fn` has stopped
|
133 |
|
134 | ```js
|
135 | var count = 0
|
136 |
|
137 | fw.whilst(
|
138 | function () {
|
139 | return count < 3
|
140 | },
|
141 | function (callback) {
|
142 | count++
|
143 | setTimeout(callback, 1000)
|
144 | },
|
145 | function (err) {
|
146 | // 3 seconds have passed
|
147 | }
|
148 | )
|
149 | ```
|
150 |
|
151 | ### each(arr, iterator, callback)
|
152 | **Alias**: `map, eachParallel, mapParallel`
|
153 |
|
154 | Applies the function iterator to each item in arr, in parallel.
|
155 | The iterator is called with an item from the list, and a callback for when it has finished
|
156 |
|
157 | Note that since this function applies iterator to each item in parallel,
|
158 | there is no guarantee that the iterator functions will complete in order
|
159 |
|
160 | ##### arguments
|
161 |
|
162 | - **arr** - An array to iterate over
|
163 | - **iterator(item, callback)** - A function to apply to each item in arr.
|
164 | The iterator is passed a callback(err) which must be called once it has completed.
|
165 | If no error has occured, the callback should be run without arguments or with an explicit null argument
|
166 | - **callback(err)** - A callback which is called when all iterator functions have finished, or an error occurs
|
167 |
|
168 | ```js
|
169 | var fs = require('fs')
|
170 | var files = ['package.json', 'bower.json']
|
171 |
|
172 | fw.each(files, fs.readFile, function (err, results) {
|
173 | console.log(err) // → undefined
|
174 | console.log(results) // → [Buffer, Buffer]
|
175 | })
|
176 | ```
|
177 |
|
178 | ### eachSeries(arr, iterator, callback)
|
179 | **Alias**: `mapSeries`
|
180 |
|
181 | The same as `each()`, but only iterator is applied to
|
182 | each item in the array in series
|
183 |
|
184 | The next iterator is only called once the current one has completed (sequentially)
|
185 |
|
186 | ```js
|
187 | var fs = require('fs')
|
188 | var files = ['package.json', 'bower.json']
|
189 |
|
190 | fw.eachSeries(files, fs.readFile, function (err, results) {
|
191 | console.log(err) // → undefined
|
192 | console.log(results) // → [Buffer, Buffer]
|
193 | })
|
194 | ```
|
195 |
|
196 | ## Contributing
|
197 |
|
198 | Wanna help? Great! It will be really apreciated :)
|
199 |
|
200 | You must add new test cases for any new feature or refactor you do,
|
201 | always following the same design/code patterns that already exist
|
202 |
|
203 | ### Development
|
204 |
|
205 | Only [node.js](http://nodejs.org) is required for development
|
206 |
|
207 | Clone/fork this repository
|
208 | ```
|
209 | $ git clone https://github.com/h2non/fw.git && cd fw
|
210 | ```
|
211 |
|
212 | Install dependencies
|
213 | ```
|
214 | $ npm install
|
215 | ```
|
216 |
|
217 | Compile code
|
218 | ```
|
219 | $ make compile
|
220 | ```
|
221 |
|
222 | Run tests
|
223 | ```
|
224 | $ make test
|
225 | ```
|
226 |
|
227 | Generate browser sources
|
228 | ```
|
229 | $ make browser
|
230 | ```
|
231 |
|
232 | ## License
|
233 |
|
234 | [MIT](http://opensource.org/licenses/MIT) © Tomas Aparicio
|
235 |
|
236 | [travis]: http://travis-ci.org/h2non/fw
|
237 | [npm]: http://npmjs.org/package/fw
|
238 | [hu]: https://github.com/h2non/hu
|