time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

README.md (10352B)


      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 # inmapAsync
     22 
     23 > Invoke a function for each element in a collection and update the collection in-place.
     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 inmapAsync = require( '@stdlib/utils/async/inmap' );
     41 ```
     42 
     43 #### inmapAsync( collection, \[options,] fcn, done )
     44 
     45 Invokes a function for each element in a `collection` and updates the `collection` in-place.
     46 
     47 <!-- eslint-disable no-use-before-define -->
     48 
     49 ```javascript
     50 function fcn( value, index, next ) {
     51     setTimeout( onTimeout, value );
     52     function onTimeout() {
     53         console.log( value );
     54         next( null, value*index );
     55     }
     56 }
     57 
     58 function done( error, collection ) {
     59     if ( error ) {
     60         throw error;
     61     }
     62     console.log( collection === arr );
     63     console.log( collection );
     64 }
     65 
     66 var arr = [ 3000, 2500, 1000 ];
     67 
     68 inmapAsync( arr, fcn, done );
     69 /*
     70     1000
     71     2500
     72     3000
     73     true
     74     [ 0, 2500, 2000 ]
     75 */
     76 ```
     77 
     78 The `next` callback accepts two arguments: `error` and `result`. The second argument to the `next` callback is used to update the `collection` element for the corresponding collection `index`, thus mutating the input `collection`.
     79 
     80 ```javascript
     81 function fcn( value, index, next ) {
     82     setTimeout( onTimeout, value );
     83     function onTimeout() {
     84         next( null, 'beep: '+index );
     85     }
     86 }
     87 
     88 function done( error, collection ) {
     89     if ( error ) {
     90         throw error;
     91     }
     92     console.log( collection );
     93     // => [ 'beep: 0', 'beep: 1', 'beep: 2' ]
     94 }
     95 
     96 var arr = [ 3000, 2500, 1000 ];
     97 
     98 inmapAsync( arr, fcn, done );
     99 ```
    100 
    101 If the `next` callback is called with an `error` argument, the input `collection` may be **partially** mutated.
    102 
    103 ```javascript
    104 function fcn( value, index, next ) {
    105     setTimeout( onTimeout, value );
    106     function onTimeout() {
    107         if ( index === 1 ) {
    108             return next( new Error( 'boop' ) );
    109         }
    110         next( null, 'beep: '+index );
    111     }
    112 }
    113 
    114 function done( error, collection ) {
    115     if ( error ) {
    116         // Ignore error...
    117     }
    118     console.log( collection );
    119     // => [ 'beep: 0', 2000, 3000 ]
    120 }
    121 
    122 var arr = [ 1000, 2000, 3000 ];
    123 
    124 inmapAsync( arr, fcn, done );
    125 ```
    126 
    127 The function accepts the following `options`:
    128 
    129 -   `limit`: the maximum number of pending invocations at any one time. Default: `infinity`.
    130 -   `series`: `boolean` indicating whether to sequentially invoke `fcn` for each `collection` element. If `true`, the function sets `options.limit=1`. Default: `false`.
    131 -   `thisArg`: the execution context for `fcn`.
    132 
    133 By default, all elements are processed concurrently, which means that the function does **not** guarantee completion order. To process each `collection` element sequentially, set the `series` option to `true`.
    134 
    135 <!-- eslint-disable no-use-before-define -->
    136 
    137 ```javascript
    138 function fcn( value, index, next ) {
    139     setTimeout( onTimeout, value );
    140     function onTimeout() {
    141         console.log( value );
    142         next( null, value*index );
    143     }
    144 }
    145 
    146 function done( error, collection ) {
    147     if ( error ) {
    148         throw error;
    149     }
    150     console.log( collection === arr );
    151     console.log( collection );
    152 }
    153 
    154 var arr = [ 3000, 2500, 1000 ];
    155 
    156 var opts = {
    157     'series': true
    158 };
    159 
    160 inmapAsync( arr, opts, fcn, done );
    161 /* =>
    162     3000
    163     2500
    164     1000
    165     true
    166     [ 0, 2500, 2000 ]
    167 */
    168 ```
    169 
    170 To limit the maximum number of pending function invocations, set the `limit` option.
    171 
    172 <!-- eslint-disable no-use-before-define -->
    173 
    174 ```javascript
    175 function fcn( value, index, next ) {
    176     setTimeout( onTimeout, value );
    177     function onTimeout() {
    178         console.log( value );
    179         next( null, value*index );
    180     }
    181 }
    182 
    183 function done( error, collection ) {
    184     if ( error ) {
    185         throw error;
    186     }
    187     console.log( collection === arr );
    188     console.log( collection );
    189 }
    190 
    191 var arr = [ 3000, 2500, 1000 ];
    192 
    193 var opts = {
    194     'limit': 2
    195 };
    196 
    197 inmapAsync( arr, opts, fcn, done );
    198 /* =>
    199     2500
    200     3000
    201     1000
    202     true,
    203     [ 0, 2500, 2000 ]
    204 */
    205 ```
    206 
    207 To set the execution context of `fcn`, set the `thisArg` option.
    208 
    209 <!-- eslint-disable no-use-before-define -->
    210 
    211 ```javascript
    212 function fcn( value, index, next ) {
    213     this.count += 1;
    214     setTimeout( onTimeout, value );
    215     function onTimeout() {
    216         next( null, value*index );
    217     }
    218 }
    219 
    220 var arr = [ 3000, 2500, 1000 ];
    221 
    222 var context = {
    223     'count': 0
    224 };
    225 
    226 var opts = {
    227     'thisArg': context
    228 };
    229 
    230 inmapAsync( arr, opts, fcn, done );
    231 
    232 function done( error, collection ) {
    233     if ( error ) {
    234         throw error;
    235     }
    236     console.log( collection === arr );
    237     // => true
    238 
    239     console.log( collection );
    240     // => [ 0, 2500, 2000 ]
    241 
    242     console.log( context.count );
    243     // => 3
    244 }
    245 ```
    246 
    247 When invoked, `fcn` is provided a maximum of four arguments:
    248 
    249 -   `value`: collection value.
    250 -   `index`: collection index.
    251 -   `collection`: the input `collection`.
    252 -   `next`: a callback which should be called once `fcn` has finished processing a collection `value`.
    253 
    254 The actual number of provided arguments depends on function `length`. If `fcn` accepts two arguments, `fcn` is provided `value` and `next`. If `fcn` accepts three arguments, `fcn` is provided `value`, `index`, and `next`. For every other `fcn` signature, `fcn` is provided all four arguments.
    255 
    256 <!-- eslint-disable no-use-before-define -->
    257 
    258 ```javascript
    259 function fcn( value, i, collection, next ) {
    260     console.log( 'collection: %s. %d: %d', collection.join( ',' ), i, value );
    261     setTimeout( onTimeout, value );
    262     function onTimeout() {
    263         console.log( value );
    264         next( null, value*i );
    265     }
    266 }
    267 
    268 function done( error, collection ) {
    269     if ( error ) {
    270         throw error;
    271     }
    272     console.log( collection === arr );
    273     // => true
    274 
    275     console.log( collection );
    276     // => [ 0, 2500, 2000 ]
    277 }
    278 
    279 var arr = [ 3000, 2500, 1000 ];
    280 
    281 inmapAsync( arr, fcn, done );
    282 /* =>
    283     collection: 3000,2500,1000. 0: 3000
    284     collection: 3000,2500,1000. 1: 2500
    285     collection: 3000,2500,1000. 2: 1000
    286     1000
    287     2500
    288     3000
    289 */
    290 ```
    291 
    292 #### inmapAsync.factory( \[options,] fcn )
    293 
    294 Returns a `function` which invokes a function once for each element in a `collection`.
    295 
    296 ```javascript
    297 function fcn( value, index, next ) {
    298     setTimeout( onTimeout, value );
    299     function onTimeout() {
    300         console.log( value );
    301         next( null, value*index );
    302     }
    303 }
    304 
    305 function done( error, collection ) {
    306     if ( error ) {
    307         throw error;
    308     }
    309     console.log( collection );
    310 }
    311 
    312 var f = inmapAsync.factory( fcn );
    313 
    314 var arr1 = [ 3000, 2500, 1000 ];
    315 
    316 f( arr1, done );
    317 /* =>
    318     1000
    319     2500
    320     3000
    321     [ 0, 2500, 2000 ]
    322 */
    323 
    324 var arr2 = [ 300, 250, 100 ];
    325 
    326 f( arr2, done );
    327 /* =>
    328     100
    329     250
    330     300
    331     [ 0, 250, 200 ]
    332 */
    333 ```
    334 
    335 The function accepts the same `options` as `inmapAsync()`.
    336 
    337 </section>
    338 
    339 <!-- /.usage -->
    340 
    341 <!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
    342 
    343 <section class="notes">
    344 
    345 ## Notes
    346 
    347 -   A `collection` may be either an [`Array`][mdn-array], [`Typed Array`][mdn-typed-array], or an array-like [`Object`][mdn-object] (excluding `strings` and `functions`).
    348 -   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.
    349 -   The function invokes the `done` callback with the input `collection` provided as the second argument.
    350 -   The function modifies `collection` elements in-place.
    351 -   The function does **not** support dynamic `collection` resizing.
    352 -   The function does **not** skip `undefined` elements.
    353 -   **Neither** `inmapAsync` 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`).
    354 
    355 </section>
    356 
    357 <!-- /.notes -->
    358 
    359 <!-- Package usage examples. -->
    360 
    361 <section class="examples">
    362 
    363 ## Examples
    364 
    365 <!-- eslint no-undef: "error" -->
    366 
    367 ```javascript
    368 var resolve = require( 'path' ).resolve;
    369 var readFile = require( '@stdlib/fs/read-file' );
    370 var inmapAsync = require( '@stdlib/utils/async/inmap' );
    371 
    372 var files = [
    373     resolve( __dirname, 'package.json' ),
    374     resolve( __dirname, 'README.md' )
    375 ];
    376 
    377 function done( error, results ) {
    378     if ( error ) {
    379         throw error;
    380     }
    381     console.log( results );
    382 }
    383 
    384 function read( file, next ) {
    385     var opts = {
    386         'encoding': 'utf8'
    387     };
    388     readFile( file, opts, onFile );
    389 
    390     function onFile( error, data ) {
    391         if ( error ) {
    392             error = new Error( 'unable to read file: '+file );
    393             return next( error );
    394         }
    395         next( null, data );
    396     }
    397 }
    398 
    399 inmapAsync( files, read, done );
    400 ```
    401 
    402 </section>
    403 
    404 <!-- /.examples -->
    405 
    406 <!-- 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. -->
    407 
    408 <section class="references">
    409 
    410 </section>
    411 
    412 <!-- /.references -->
    413 
    414 <!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
    415 
    416 <section class="links">
    417 
    418 [mdn-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
    419 
    420 [mdn-typed-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
    421 
    422 [mdn-object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
    423 
    424 </section>
    425 
    426 <!-- /.links -->