# whileAsync > Invoke a function while a test condition is true.
## Usage ```javascript var whileAsync = require( '@stdlib/utils/async/while' ); ``` #### whileAsync( predicate, fcn, done\[, thisArg ] ) Invokes a `function` until a `predicate` function returns `false`. ```javascript function predicate( i, clbk ) { clbk( null, i < 5 ); } function fcn( i, next ) { setTimeout( onTimeout, 0 ); function onTimeout() { console.log( 'beep: %d', i ); next(); } } function done( error ) { if ( error ) { throw error; } } whileAsync( predicate, fcn, done ); /* => beep: 0 beep: 1 beep: 2 beep: 3 beep: 4 */ ``` The `predicate` function is provided two arguments: - `i`: iteration number (starting from zero) - `clbk`: a callback indicating whether to invoke `fcn` The `clbk` function accepts two arguments: - `error`: error object - `bool`: test result If the test result is truthy, the function invokes `fcn`; otherwise, the function invokes the `done` callback. The function to invoke is provided two arguments: - `i`: iteration number (starting from zero) - `next`: a callback which must be invoked before proceeding to the next iteration 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. ```javascript function predicate( i, clbk ) { clbk( null, i < 5 ); } function fcn( i, next ) { setTimeout( onTimeout, 0 ); function onTimeout() { next( new Error( 'beep' ) ); } } function done( error ) { console.error( error.message ); // => beep } whileAsync( predicate, fcn, done ); ``` The `done` callback is invoked with an `error` argument and any arguments passed to the final `next` callback. ```javascript function predicate( i, clbk ) { clbk( null, i < 5 ); } function fcn( i, next ) { setTimeout( onTimeout, 0 ); function onTimeout() { next( null, i ); } } function done( error, result ) { if ( error ) { throw error; } console.log( result ); // => 4 } whileAsync( predicate, fcn, done ); ``` To set the function execution context for the invoked function, provide a `thisArg`. ```javascript function predicate( i, clbk ) { clbk( null, i < 5 ); } function fcn( i, next ) { this.count += 1; setTimeout( onTimeout, 0 ); function onTimeout() { next(); } } var context = { 'count': 0 }; whileAsync( predicate, fcn, done, context ); function done( error ) { if ( error ) { throw error; } console.log( context.count ); // => 5 } ```
## Notes - 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`).
## Examples ```javascript var repeatString = require( '@stdlib/string/repeat' ); var whileAsync = require( '@stdlib/utils/async/while' ); function predicate( i, clbk ) { setTimeout( onTimeout, 0 ); function onTimeout() { clbk( null, i < 5 ); } } function fcn( i, next ) { setTimeout( onTimeout, 0 ); function onTimeout() { next( null, repeatString( 'beep', i+1 ) ); } } function done( error, result ) { if ( error ) { throw error; } console.log( result ); } whileAsync( predicate, fcn, done ); ```