README.md (5343B)
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 # untilAsync 22 23 > Invoke a function until 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 untilAsync = require( '@stdlib/utils/async/until' ); 41 ``` 42 43 #### untilAsync( predicate, fcn, done\[, thisArg ] ) 44 45 Invokes a `function` until a `predicate` function returns `true`. 46 47 ```javascript 48 function predicate( i, clbk ) { 49 clbk( null, i >= 5 ); 50 } 51 52 function fcn( i, next ) { 53 setTimeout( onTimeout, 0 ); 54 function onTimeout() { 55 console.log( 'beep: %d', i ); 56 next(); 57 } 58 } 59 60 function done( error ) { 61 if ( error ) { 62 throw error; 63 } 64 } 65 66 untilAsync( predicate, fcn, done ); 67 /* => 68 beep: 0 69 beep: 1 70 beep: 2 71 beep: 3 72 beep: 4 73 */ 74 ``` 75 76 The `predicate` function is provided two arguments: 77 78 - `i`: iteration number (starting from zero) 79 - `clbk`: a callback indicating whether to invoke `fcn` 80 81 The `clbk` function accepts two arguments: 82 83 - `error`: error object 84 - `bool`: test result 85 86 If the test result is falsy, the function invokes `fcn`; otherwise, the function invokes the `done` callback. 87 88 The function to invoke is provided two arguments: 89 90 - `i`: iteration number (starting from zero) 91 - `next`: a callback which must be invoked before proceeding to the next iteration 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 predicate( i, clbk ) { 97 clbk( null, i >= 5 ); 98 } 99 100 function fcn( i, next ) { 101 setTimeout( onTimeout, 0 ); 102 function onTimeout() { 103 next( new Error( 'beep' ) ); 104 } 105 } 106 107 function done( error ) { 108 console.error( error.message ); 109 // => beep 110 } 111 112 untilAsync( predicate, fcn, 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 predicate( i, clbk ) { 119 clbk( null, i >= 5 ); 120 } 121 122 function fcn( i, next ) { 123 setTimeout( onTimeout, 0 ); 124 function onTimeout() { 125 next( null, i ); 126 } 127 } 128 129 function done( error, result ) { 130 if ( error ) { 131 throw error; 132 } 133 console.log( result ); 134 // => 4 135 } 136 137 untilAsync( predicate, fcn, 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 predicate( i, clbk ) { 146 clbk( null, i >= 5 ); 147 } 148 149 function fcn( i, next ) { 150 this.count += 1; 151 setTimeout( onTimeout, 0 ); 152 function onTimeout() { 153 next(); 154 } 155 } 156 157 var context = { 158 'count': 0 159 }; 160 161 untilAsync( predicate, fcn, 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 untilAsync = require( '@stdlib/utils/async/until' ); 199 200 function predicate( i, clbk ) { 201 setTimeout( onTimeout, 0 ); 202 function onTimeout() { 203 clbk( null, i >= 5 ); 204 } 205 } 206 207 function fcn( i, next ) { 208 setTimeout( onTimeout, 0 ); 209 function onTimeout() { 210 next( null, repeatString( 'beep', i+1 ) ); 211 } 212 } 213 214 function done( error, result ) { 215 if ( error ) { 216 throw error; 217 } 218 console.log( result ); 219 } 220 221 untilAsync( predicate, fcn, 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 -->