Countdown timer on setTimeout
Sometimes we need simple countdown. Next example allows handle each tick and abort the timer.
Task:
- Execute tick every
timeout
milliseconds - Each tick should send remain seconds to listeners
- Countdown can be stopped (
abort
argument) - Countdown can't be started if already started
function createCountdown( name, {start, abort = createEvent(`${name}Reset`), timeout = 1000},) { // tick every 1 second const $working = createStore(true, {name: `${name}Working`}) const tick = createEvent(`${name}Tick`) const timerFx = createEffect(`${name}Timer`).use(() => wait(timeout))
$working.on(abort, () => false).on(start, () => true)
guard({ source: start, filter: timerFx.pending.map(is => !is), target: tick, })
forward({ from: tick, to: timerFx, })
const willTick = guard({ source: timerFx.done.map(({params}) => params - 1), filter: seconds => seconds >= 0, })
guard({ source: willTick, filter: $working, target: tick, })
return {tick}}
function wait(ms) { return new Promise(resolve => { setTimeout(resolve, ms) })}
Usage:
const startCountdown = createEvent()const abortCountdown = createEvent()
const countdown = createCountdown('simple', { start: startCountdown, abort: abortCountdown,})
// handle each tickcountdown.tick.watch(remainSeconds => { console.info('Tick. Remain seconds: ', remainSeconds)})
// let's startstartCountdown(15) // 15 ticks to count down, 1 tick per second
// abort after 5 secondsetTimeout(abortCountdown, 5000)