# untilAsync
> Invoke a function until a test condition is true.
## Usage
```javascript
var untilAsync = require( '@stdlib/utils/async/until' );
```
#### untilAsync( predicate, fcn, done\[, thisArg ] )
Invokes a `function` until a `predicate` function returns `true`.
```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;
    }
}
untilAsync( 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 falsy, 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
}
untilAsync( 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
}
untilAsync( 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
};
untilAsync( 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 untilAsync = require( '@stdlib/utils/async/until' );
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 );
}
untilAsync( predicate, fcn, done );
```