Countdown timer on setTimeout
Sometimes we need simple countdown. Next example allows us to handle each tick and abort the timer.
Task:
- Execute tick every timeoutmilliseconds
- Each tick should send left seconds to listeners
- Countdown can be stopped (abortargument)
- 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) Effector
Effector