Skip to content

parzh/recursive-timeout

Repository files navigation

recursive-timeout

npm version License: MIT

A simple solution to a classic problem: setInterval implemented as recursive setTimeout calls.

This package is designed to be a drop-in replacement for the normal setInterval.

"Why exactly do I need this?"

Take a look at this section from javascript.info, it outlines the problem and the solution.

Basically, the normal setInterval doesn't wait for the callback to happen, – it schedules the next iteration right away:

function runsForOneSecond() {
  const startTime = Date.now()

  while (Date.now() - startTime < 1000) { /* just wait */ }

  console.log(Date.now(), 'Done!')
}

console.log(Date.now(), 'Start')
setInterval(runsForOneSecond, 500)
// logs (approximately):
// 1234567890000 Start
// 1234567891500 Done!
// 1234567892500 Done!
// 1234567893500 Done!

… while the "recursive timeout" approach necessarily waits for the callback to finish before scheduling the next call:

import { setRecursive } from 'recursive-timeout'

console.log(Date.now(), 'Start')
setRecursive(runsForOneSecond, 500)
// logs (approximately):
// 1234567890000 Start
// 1234567891500 Done!
// 1234567893000 Done!
// 1234567894500 Done!

Features

  • Dual Module Support: Works seamlessly with both ECMAScript Modules (import) and CommonJS (require).
  • Familiar API: Designed as a drop-in replacement for setInterval.
  • Promise-based API: ⚠️ (coming soon) ⚠️ A promise-based interface for use with asynchronous callbacks.

Installation

npm install recursive-timeout

Usage

The straightforward API of setRecursive and clearRecursive mirrors the native setInterval and clearInterval functions.

ECMAScript

This is the standard way to use the package, ideal for most cases.

import { setRecursive, clearRecursive } from 'recursive-timeout'

setRecursive(() => console.log('hi'), 1000)
setRecursive(console.log, 1000, 'hi')

To cancel the interval, pass the timer into clearRecursive or the standard clearInterval, or even clearTimeout:

const recursive = setRecursive(console.log, 1000, 'hi')

clearRecursive(recursive)
clearInterval(recursive) // ✅ works
clearTimeout(recursive) // ✅ also works

For TypeScript users, some additional checks are added:

function sum(a: number, b: number): void {
  console.log(a + b)
}

setRecursive(sum, 100)
// ❌ Error: not enough arguments

setRecursive(sum, 100, 42)
// ❌ Error: not enough arguments

setRecursive(sum, 100, 42, 17)
// ✅ OK (logs 59 every ~100 milliseconds)

ECMAScript (promise-based) – coming soon ⚠️

import { setRecursive, clearRecursive } from 'recursive-timeout/promises'
import { promises } from 'recursive-timeout'

promises.setRecursive()
promises.clearRecursive()

CommonJS

const { setRecursive, clearRecursive } = require('recursive-timeout')

CommonJS (promise-based) – coming soon ⚠️

const { setRecursive, clearRecursive } = require('recursive-timeout/promises')
const { promises } = require('recursive-timeout')

promises.setRecursive()
promises.clearRecursive()

License

This project is licensed under the MIT License.

About

`setInterval` implemented as a recursive `setTimeout`

Resources

License

Stars

Watchers

Forks