repeat-function-call-timer
v1.0.7
Published
Repeat or retry a function call until it returns a specific value or a timeout is reached
Maintainers
Readme
Repeat function-call timer
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 <[email protected]>
Synopsis
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 )Parameters
functionToCall
Function to repeat
- Returning a target value that allows matching expectedValue to exit repetition
- Use no or an intentionally unmatchable return to exit on timeout only
- Intentionally left to be defined in detail by individual use cases to gain maximum flexibility
- Intentionally no parameters
- Parameters may introduce complexity that might not be easy to control
- You may use whenInterval to manipulate an external environment at runtime to be listened to by functionToCall
- 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 Details / Examples)
expectedValue
Value to compare with return of functionToCall to exit repetition
- Can only be a Primitive Type (except Symbol), i.e. null or of type bigint / boolean / number / string / undefined
- For working with Arrays, Errors, Functions, Objects, Maps or RegExps you would use a wrapper functionToCall with an own comparison method returning true or false
- Use an intentionally unmatchable value to exit on timeout only
timeout
Timespan in milliseconds to repeat functionToCall to match expectedValue before giving up
- Use no or an intentionally unmatchable return of functionToCall or an intentionally unmatchable value to exit on timeout only
interval
Timespan in milliseconds to wait before next repetition
whenInterval
optional: Callback on start of new interval
- Hook for injecting actions
- Parameter:
passedTime: The time passed since start. May be used for analyses. - Note: Does not allow to manipulate internal parameters at runtime, but you may manipulate an external environment to be listened to by functionToCall
Returns
Examples
As observer
Do something only if an observed process set a value
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 }Do different things depending if another asynchronous process set a value
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 } })Tracking an observed process that sets trackable values
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`) } })
For plain repetition
Log current time's seconds while doing something else
repeatFunctionCallTimer( ()=>console.log(new Date().getSeconds()), '', 3000, 1000 ); // ... meanwhile something else ...Log current time's seconds before doing something else
await repeatFunctionCallTimer( ()=>console.log(new Date().getSeconds()), '', 3000, 1000 ); // ... afterwards something else ...
Demos
See demos
Caveats
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)
Installation
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-timerDetails
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()/awaitis available, the defined timeout can intercept if athen()/awaitthat 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
Tests
- Code tests to be run with Node.js / Bun available in Source Code
