README.md (6418B)
1 <!-- 2 3 @license Apache-2.0 4 5 Copyright (c) 2018 The Stdlib Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 19 --> 20 21 # mapFunAsync 22 23 > Invoke a function `n` times and return an array of accumulated function return values. 24 25 <!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. --> 26 27 <section class="intro"> 28 29 </section> 30 31 <!-- /.intro --> 32 33 <!-- Package usage documentation. --> 34 35 <section class="usage"> 36 37 ## Usage 38 39 ```javascript 40 var mapFunAsync = require( '@stdlib/utils/async/map-function' ); 41 ``` 42 43 #### mapFunAsync( fcn, n, \[options,] done ) 44 45 Invokes a function `n` times and returns an `array` of accumulated function return values. 46 47 ```javascript 48 function fcn( i, next ) { 49 var t = 300 - (i*50); 50 setTimeout( onTimeout, t ); 51 function onTimeout() { 52 console.log( i ); 53 next( null, i ); 54 } 55 } 56 57 function done( error, arr ) { 58 if ( error ) { 59 throw error; 60 } 61 console.log( arr ); 62 } 63 64 mapFunAsync( fcn, 5, done ); 65 /* => 66 4 67 3 68 2 69 1 70 0 71 [ 0, 1, 2, 3, 4 ] 72 */ 73 ``` 74 75 For each iteration, the provided function is invoked with two arguments: 76 77 - `index`: invocation index (starting from zero) 78 - `next`: callback to be invoked upon function completion 79 80 The `next` callback accepts two arguments: 81 82 - `error`: error argument 83 - `result`: function result 84 85 The function accepts the following `options`: 86 87 - `limit`: the maximum number of pending invocations at any one time. Default: `infinity`. 88 - `series`: `boolean` indicating whether to sequentially invoke `fcn`. If `true`, the function sets `options.limit=1`. Default: `false`. 89 - `thisArg`: the execution context for `fcn`. 90 91 By default, all invocations are performed concurrently, which means that the function does **not** guarantee completion order. To invoke a function such that only one invocation is pending at any one time, set the `series` option to `true`. 92 93 ```javascript 94 function fcn( i, next ) { 95 var t = 300 - (i*50); 96 setTimeout( onTimeout, t ); 97 function onTimeout() { 98 console.log( i ); 99 next( null, i ); 100 } 101 } 102 103 function done( error, arr ) { 104 if ( error ) { 105 throw error; 106 } 107 console.log( arr ); 108 } 109 110 var opts = { 111 'series': true 112 }; 113 114 mapFunAsync( fcn, 5, opts, done ); 115 /* => 116 0 117 1 118 2 119 3 120 4 121 [ 0, 1, 2, 3, 4 ] 122 */ 123 ``` 124 125 To limit the maximum number of pending function invocations, set the `limit` option. 126 127 ```javascript 128 var delays = [ 300, 250, 225, 150, 100 ]; 129 130 function fcn( i, next ) { 131 setTimeout( onTimeout, delays[ i ] ); 132 function onTimeout() { 133 console.log( i ); 134 next( null, i ); 135 } 136 } 137 138 function done( error, arr ) { 139 if ( error ) { 140 throw error; 141 } 142 console.log( arr ); 143 } 144 145 var opts = { 146 'limit': 2 147 }; 148 149 mapFunAsync( fcn, 5, opts, done ); 150 /* => 151 1 152 0 153 3 154 2 155 4 156 [ 0, 1, 2, 3, 4 ] 157 */ 158 ``` 159 160 To set the execution context of `fcn`, set the `thisArg` option. 161 162 <!-- eslint-disable no-invalid-this --> 163 164 ```javascript 165 function fcn( i, next ) { 166 this.count += 1; 167 setTimeout( onTimeout, 0 ); 168 function onTimeout() { 169 next( null, i ); 170 } 171 } 172 173 function done( error, arr ) { 174 if ( error ) { 175 throw error; 176 } 177 console.log( arr ); 178 // => [ 0, 1, 2, 3, 4 ] 179 } 180 181 var ctx = { 182 'count': 0 183 }; 184 var opts = { 185 'thisArg': ctx 186 }; 187 188 mapFunAsync( fcn, 5, opts, done ); 189 ``` 190 191 #### mapFunAsync.factory( \[options,] fcn ) 192 193 Returns a `function` which invokes a function `n` times and returns an `array` of accumulated function return values. 194 195 ```javascript 196 function fcn( i, next ) { 197 var t = 300 - (i*50); 198 setTimeout( onTimeout, t ); 199 function onTimeout() { 200 console.log( i ); 201 next( null, i ); 202 } 203 } 204 205 function done( error, arr ) { 206 if ( error ) { 207 throw error; 208 } 209 console.log( arr ); 210 } 211 212 var opts = { 213 'series': true 214 }; 215 216 var f = mapFunAsync.factory( opts, fcn ); 217 218 f( 5, done ); 219 /* => 220 0 221 1 222 2 223 3 224 4 225 [ 0, 1, 2, 3, 4 ] 226 */ 227 228 f( 2, done ); 229 /* => 230 0 231 1 232 [ 0, 1 ] 233 */ 234 ``` 235 236 The function accepts the same `options` as `mapFunAsync()`. 237 238 </section> 239 240 <!-- /.usage --> 241 242 <!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 243 244 <section class="notes"> 245 246 ## Notes 247 248 - If a provided function calls the `next` callback with a truthy `error` argument, the function suspends execution and immediately calls the `done` callback for subsequent `error` handling. 249 - **Neither** `mapFunAsync` nor the function returned by the `factory` method **guarantee** asynchronous execution. To guarantee asynchrony, wrap the `done` callback in a function which either executes at the end of the current stack (e.g., `nextTick`) or during a subsequent turn of the event loop (e.g., `setImmediate`, `setTimeout`). 250 251 </section> 252 253 <!-- /.notes --> 254 255 <!-- Package usage examples. --> 256 257 <section class="examples"> 258 259 ## Examples 260 261 <!-- eslint no-undef: "error" --> 262 263 ```javascript 264 var randu = require( '@stdlib/random/base/randu' ); 265 var mapFunAsync = require( '@stdlib/utils/async/map-function' ); 266 267 function rand( i, next ) { 268 var t = randu() * i; 269 setTimeout( onTimeout, t ); 270 function onTimeout() { 271 next( null, t ); 272 } 273 } 274 275 function done( error, out ) { 276 if ( error ) { 277 throw error; 278 } 279 console.log( out ); 280 } 281 282 mapFunAsync( rand, 10, done ); 283 ``` 284 285 </section> 286 287 <!-- /.examples --> 288 289 <!-- Section to include cited references. If references are included, add a horizontal rule *before* the section. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 290 291 <section class="references"> 292 293 </section> 294 295 <!-- /.references --> 296 297 <!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 298 299 <section class="links"> 300 301 </section> 302 303 <!-- /.links -->