Interactive, stateful JS (ES6) timeout interface
The setTimeout() and clearTimeout() primitives are fine for basic functionality, but they leave much to be desired. For example, JS provides no means by which to test if a timeout has finished executing, still waiting to be executed, or if has been cleared.
The Timeout object seeks to improve the situation by allowing you to:
- set and clear timeouts the same way you've always done
- check if a particular timeout has been created or cleared
- check if a timeout is pending execution or if it has already executed
You can use a human-readable identifier to uniquely identify a timeout or the callback itself will be used as its own unique identifier. Checkout the examples below. You can also play around with a demo at this CodePen and read a little more at this Medium article.
- npm install smart-timeout
import Timeout from 'smart-timeout'-or-const Timeout = require('smart-timeout');
Timeout.set(keyName, function, millisecs = 0, param1, param2, ...)- schedulefunctionto execute aftermillisecs, identified bykeyNameTimeout.set(function, millisecs = 0, param1, param2, ...)- same as above, except identifiable byfunctionitselfTimeout.exists(key)- returns true if function has been defined and not erased, whether or not it has executedTimeout.pending(key)- returns true if function exists and has not yet executedTimeout.remaining(key)- returns milliseconds remaining in the countdown until executionTimeout.executed(key)- returns true if function exists and has executedTimeout.pause(key)- pauses a function that exists but has not yet executedTimeout.paused(key)- returns true if function exists and is currently pausedTimeout.resume(key)- allows paused execution countdown to resumeTimeout.clear(key, erase = true)- clears a scheduled countdown; by default, knowledge of its existence is erased
- implementation has been refactored significantly
pause(),paused(),resume()have been added - thanks to Pedro Muller for the suggestion!remaining()added - returns milliseconds remaining until execution- checking arguments to
set()for a function rather than making assumptions about the params - added default of
0to themsparameter ofset()
const announce = () => {
console.log('!!! hello from inside announce() !!!')
}
const showStatus = () => {
console.log('does a timeout exist for announce()?', Timeout.exists(announce))
console.log('is announce pending?', Timeout.pending(announce))
console.log('did announce execute?', Timeout.executed(announce))
}
console.log('--- before setting the timeout. status check:')
showStatus()
const ran = Timeout.set(announce, 1000)
console.log('--- just set the timeout. status check:')
showStatus()
console.log('ran() = ', ran())
Timeout.set(() => {
console.log('--- 1 second elapsed. status check:')
showStatus()
console.log('ran() = ', ran())
Timeout.clear(announce)
console.log('--- cleared timeout. status check:')
showStatus()
console.log('ran() = ', ran())
}, 1000)
// use the callback as the key to set a timeout that does nothing but
// tracks whether the timeout has executed
const throttle = (delay, callback) =>
(...args) =>
!Timeout.pending(callback) && Timeout.set(callback, () => {}, delay)
? callback.apply(this, args)
: null
const onScroll = () => {
const isScrolled = $(window).scrollTop() > 0
$('html').toggleClass('is-scrolled', isScrolled)
}
const onScrollThrottled = throttle(100, onScroll)
$(window).scroll(onScrollThrottled)