Repeat or retry a function call until it returns a specific value or a timeout is reached.
Created for handling / observing intermediate or final states of asynchronous processes (see Details), but also helpful for other things (see Examples).
hh lohmann <hh.lohmann@gmail.com>
import { repeatFunctionCallTimer } from 'repeat-function-call-timer'
repeatFunctionCallTimer( functionToCall, expectedValue, timeout, interval )
await repeatFunctionCallTimer( functionToCall, expectedValue, timeout, interval )
const res = await repeatFunctionCallTimer( functionToCall, expectedValue, timeout, interval )
if(res.match) ...
repeatFunctionCallTimer( functionToCall, expectedValue, timeout, interval )
.then(res=>{
if(res.match){ ... }
else{ ... }
})
repeatFunctionCallTimer( functionToCall, expectedValue, timeout, interval, whenInterval )
Function to repeat
Value to compare with return of functionToCall to exit repetition
Timespan in milliseconds to repeat functionToCall to match expectedValue before giving up
Timespan in milliseconds to wait before next repetition
optional: Callback on start of new interval
passedTime: The time passed since start. May be used for analyses. function observerFunction(){
// ... code to check if observed value has been set by observed process ...
if(observedValueHasBeenSet) return true;
return false;
}
const res = await repeatFunctionCallTimer( observerFunction, true, 2000, 100 )
if(res.match){ // ... something only if value was set in given time }
function observerFunction(){
// ... code to check if observed value has been set by observed process ...
if(observedValueHasBeenSet) return true;
return false;
}
repeatFunctionCallTimer( observerFunction, true, 2000, 100 )
.then(res=>{
if(res.match){ // ... something only if value was set in given time }
else{ // ... something if value was no set in given time }
})
function observerFunction(){
// ... code to check current values set by observed process ...
if(observedValue==='reading') return console.log('Reading data...');
if(observedValue==='processing') return console.log('Processing data...');
if(observedValue==='writing') return console.log('Writing data...');
if(observedValue==='fail') return 'finished';
if(observedValue==='success') return 'finished';
return 'unknown';
}
const res = await repeatFunctionCallTimer( observerFunction, 'finished', 2000, 100 )
.then(res=>{
if(res.match){ console.log(`Process XY finished - see XY's own output for details`) }
else{ console.log(`Process XY did not finish in expected time`) }
})
repeatFunctionCallTimer( ()=>console.log(new Date().getSeconds()), '', 3000, 1000 );
// ... meanwhile something else ...
await repeatFunctionCallTimer( ()=>console.log(new Date().getSeconds()), '', 3000, 1000 );
// ... afterwards something else ...
See demos
Be aware that timers in JavaScript are not exact, depending e.g. on the current Call stack. They are reliable for “normal” checking and ordering, but not for high precision orchestration which is clearly not the scope here
The functionToCall itself can not be an asynchronous function / Promise or a function returning an asynchronous function / Promise since it runs synchronously to points in time resulting from defined interval, but is intended to be usable as an observer for asynchronous functions / Promises (see Examples)
Pick for your preferred package manager:
npm i repeat-function-call-timer
pnpm i repeat-function-call-timer
bun i repeat-function-call-timer
# For Yarn you should double check docs for your and / or
# current Yarn version, newer versions do not treat `i package_name`
# as an alias for `add ...` and exclude global installations
yarn add repeat-function-call-timer
Created primarily for handling / observing intermediate or final states of asynchronous processes, especially when there is no resolving to be handled with await or .then(), but the possibility to write to a variable that can be observed by a simple functionToCall. If then() / await is available, the defined timeout can intercept if a then() / await that would set the observed variable takes too long. Using separatetly started processes communicating via an observed variable instead of e.g. one process starting another process for observing it should guarantee simplicity, flexibility and robustness.
Besides observing other processes (see above) also usable for plain repetition of an arbitrary function until an arbitrary expectedValue is matched
Intentionally no parameter for “number of tries” / “maximum number of tries”: Such parameters are dangerous without a timeout, otherwise you might wait forever (or until a system timeout) for a try without an answer, but you can always model a number of e.g. 10 tries by setting timeout as the 10th of interval
Implemented as a recursion of setTimeout calls that is terminated by timeout or matching expectedValue