time-to-botec

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

README.md (9813B)


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