Skip to content

hh-lohmann/repeat-function-call-timer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

npm package

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 <hh.lohmann@gmail.com>

This page may be displayed more optimal in its GitHub Pages view

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

  • Promise that resolves to an object with properties "match" and passedTime" => see Examples

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 on GitHub Pages for this repo

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-timer

Details

  • 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

Tests

  • Code tests to be run with Node.js / Bun available in Source Code

Source Code

References

MDN: await
MDN: Call Stack
MDN: Primitive Types (JavaScript)
MDN: Recursion
MDN: resolve
MDN: setTimeout
MDN: thenables
MDN: Using promises
MDN: Working with asynchronous functions

About

Repeat or retry a function call until it returns a specific value or a timeout is reached

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors