README.md (5496B)
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 # doWhileAsync 22 23 > Invoke a function while a test condition is true. 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 doWhileAsync = require( '@stdlib/utils/async/do-while' ); 41 ``` 42 43 #### doWhileAsync( fcn, predicate, done\[, thisArg ] ) 44 45 Invokes a `function` until a `predicate` function returns `false`. Note that the `predicate` function is evaluated **after** executing `fcn`; thus, `fcn` **always** executes at least once. 46 47 ```javascript 48 function fcn( i, next ) { 49 setTimeout( onTimeout, 0 ); 50 function onTimeout() { 51 console.log( 'beep: %d', i ); 52 next(); 53 } 54 } 55 56 function predicate( i, clbk ) { 57 clbk( null, i < 5 ); 58 } 59 60 function done( error ) { 61 if ( error ) { 62 throw error; 63 } 64 } 65 66 doWhileAsync( fcn, predicate, done ); 67 /* => 68 beep: 0 69 beep: 1 70 beep: 2 71 beep: 3 72 beep: 4 73 */ 74 ``` 75 76 The function to invoke is provided two arguments: 77 78 - `i`: iteration number (starting from zero) 79 - `next`: a callback which must be invoked before proceeding to the next iteration 80 81 The `predicate` function is provided two arguments: 82 83 - `i`: iteration number (starting from one) 84 - `clbk`: a callback indicating whether to invoke `fcn` 85 86 The `clbk` function accepts two arguments: 87 88 - `error`: error object 89 - `bool`: test result 90 91 If the test result is truthy, the function continues invoking `fcn`; otherwise, the function invokes the `done` callback. 92 93 The first argument of both `clbk` and `next` is an `error` argument. If either function is called with a truthy `error` argument, the function suspends execution and immediately calls the `done` callback for subsequent `error` handling. 94 95 ```javascript 96 function fcn( i, next ) { 97 setTimeout( onTimeout, 0 ); 98 function onTimeout() { 99 next( new Error( 'beep' ) ); 100 } 101 } 102 103 function predicate( i, clbk ) { 104 clbk( null, i < 5 ); 105 } 106 107 function done( error ) { 108 console.error( error.message ); 109 // => beep 110 } 111 112 doWhileAsync( fcn, predicate, done ); 113 ``` 114 115 The `done` callback is invoked with an `error` argument and any arguments passed to the final `next` callback. 116 117 ```javascript 118 function fcn( i, next ) { 119 setTimeout( onTimeout, 0 ); 120 function onTimeout() { 121 next( null, i ); 122 } 123 } 124 125 function predicate( i, clbk ) { 126 clbk( null, i < 5 ); 127 } 128 129 function done( error, result ) { 130 if ( error ) { 131 throw error; 132 } 133 console.log( result ); 134 // => 4 135 } 136 137 doWhileAsync( fcn, predicate, done ); 138 ``` 139 140 To set the function execution context for the invoked function, provide a `thisArg`. 141 142 <!-- eslint-disable no-invalid-this --> 143 144 ```javascript 145 function fcn( i, next ) { 146 this.count += 1; 147 setTimeout( onTimeout, 0 ); 148 function onTimeout() { 149 next(); 150 } 151 } 152 153 function predicate( i, clbk ) { 154 clbk( null, i < 5 ); 155 } 156 157 var context = { 158 'count': 0 159 }; 160 161 doWhileAsync( fcn, predicate, done, context ); 162 163 function done( error ) { 164 if ( error ) { 165 throw error; 166 } 167 console.log( context.count ); 168 // => 5 169 } 170 ``` 171 172 </section> 173 174 <!-- /.usage --> 175 176 <!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 177 178 <section class="notes"> 179 180 ## Notes 181 182 - Execution is **not** guaranteed to be asynchronous. 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`). 183 184 </section> 185 186 <!-- /.notes --> 187 188 <!-- Package usage examples. --> 189 190 <section class="examples"> 191 192 ## Examples 193 194 <!-- eslint no-undef: "error" --> 195 196 ```javascript 197 var repeatString = require( '@stdlib/string/repeat' ); 198 var doWhileAsync = require( '@stdlib/utils/async/do-while' ); 199 200 function fcn( i, next ) { 201 setTimeout( onTimeout, 0 ); 202 function onTimeout() { 203 next( null, repeatString( 'beep', i+1 ) ); 204 } 205 } 206 207 function predicate( i, clbk ) { 208 setTimeout( onTimeout, 0 ); 209 function onTimeout() { 210 clbk( null, i < 5 ); 211 } 212 } 213 214 function done( error, result ) { 215 if ( error ) { 216 throw error; 217 } 218 console.log( result ); 219 } 220 221 doWhileAsync( fcn, predicate, done ); 222 ``` 223 224 </section> 225 226 <!-- /.examples --> 227 228 <!-- 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. --> 229 230 <section class="references"> 231 232 </section> 233 234 <!-- /.references --> 235 236 <!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 237 238 <section class="links"> 239 240 </section> 241 242 <!-- /.links -->