doUntilAsync
Invoke a function until a test condition is true.
Usage
var doUntilAsync = require( '@stdlib/utils/async/do-until' );
doUntilAsync( fcn, predicate, done[, thisArg ] )
Invokes a function
until a predicate
function returns true
. Note that the predicate
function is evaluated after executing fcn
; thus, fcn
always executes at least once.
function fcn( i, next ) {
setTimeout( onTimeout, 0 );
function onTimeout() {
console.log( 'beep: %d', i );
next();
}
}
function predicate( i, clbk ) {
clbk( null, i >= 5 );
}
function done( error ) {
if ( error ) {
throw error;
}
}
doUntilAsync( fcn, predicate, done );
/* =>
beep: 0
beep: 1
beep: 2
beep: 3
beep: 4
*/
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 predicate
function is provided two arguments:
i
: iteration number (starting from one)clbk
: a callback indicating whether to invokefcn
The clbk
function accepts two arguments:
error
: error objectbool
: test result
If the test result is falsy, the function continues invoking fcn
; otherwise, the function invokes the done
callback.
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.
function fcn( i, next ) {
setTimeout( onTimeout, 0 );
function onTimeout() {
next( new Error( 'beep' ) );
}
}
function predicate( i, clbk ) {
clbk( null, i >= 5 );
}
function done( error ) {
console.error( error.message );
// => beep
}
doUntilAsync( fcn, predicate, done );
The done
callback is invoked with an error
argument and any arguments passed to the final next
callback.
function fcn( i, next ) {
setTimeout( onTimeout, 0 );
function onTimeout() {
next( null, i );
}
}
function predicate( i, clbk ) {
clbk( null, i >= 5 );
}
function done( error, result ) {
if ( error ) {
throw error;
}
console.log( result );
// => 4
}
doUntilAsync( fcn, predicate, done );
To set the function execution context for the invoked function, provide a thisArg
.
function fcn( i, next ) {
this.count += 1;
setTimeout( onTimeout, 0 );
function onTimeout() {
next();
}
}
function predicate( i, clbk ) {
clbk( null, i >= 5 );
}
var context = {
'count': 0
};
doUntilAsync( fcn, predicate, 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
var repeatString = require( '@stdlib/string/repeat' );
var doUntilAsync = require( '@stdlib/utils/async/do-until' );
function fcn( i, next ) {
setTimeout( onTimeout, 0 );
function onTimeout() {
next( null, repeatString( 'beep', i+1 ) );
}
}
function predicate( i, clbk ) {
setTimeout( onTimeout, 0 );
function onTimeout() {
clbk( null, i >= 5 );
}
}
function done( error, result ) {
if ( error ) {
throw error;
}
console.log( result );
}
doUntilAsync( fcn, predicate, done );