Delayable
Updated on August 22, 2024Source code
Delayable is a class that enriches a function, allowing it to:
- Be called after a certain number of milliseconds, on an infinite loop OR until a user-specified number of executions has been reached
- Store the number of times the function has been executed
- Store time data:
- Timestamps for each execution
- Total time elapsed since starting the delay
- Time elapsed since the last execution
- Total time remaining until all executions are complete
- Time remaining until the next execution
- Store a status (
ready,delaying, ordelayed)
In other words, Delayable implements all the main features of setTimeout and setInterval, then exposes data that describes the active timeout or interval.
Caveat when using Delayable in inactive tabs
Notably, Delayable doesn't actually use setTimeout or setInterval under the hood. Instead, it depends on Animateable, which uses requestAnimationFrame (among other dependencies) internally.
Because of this, your Delayable delays will pause when the tab is inactive (i.e. when users switch to a different tab), and will resume when the tab is active again (i.e. when users return to your tab).
This is different than the behavior you would get from setTimeout and setInterval—browsers typically (and inconsistently) throttle those timers when the tab is inactive, rather than pausing and resuming them via requestAnimationFrame.
So, just be aware: even though Delayable's API is designed to replace the setTimeout and setInterval APIs, it does work differently under the hood.
Construct a Delayable instance
The Delayable constructor accepts two parameters:
effectPasses the callback function that will be made delayable.
Your effect will receive a timestamp argument (DOMHighResTimeStamp) indicating the time since time origin.
optionsDelayable instance. See the Delayable constructor options section for more guidance.Delayable constructor options
delay0effectexecutions1Indicates the number of times the callback function will be delayed and executed.
Set executions to 1 to make it behave like setTimeout, set it to any number greater than 1 to make it delay and execute a specific number of times, and set it to true to make it behave like setInterval (i.e. delay and execute on an infinite loop).
State and methods
effectA slightly altered version of the effect you passed to the Delayable constructor. The altered effect will execute repeatedly at a rate of 60fps, and it won't call your original function until your number of milliseconds (specified in the delay option) have passed.
If you assign a value directly to effect, a setter will pass the new value to setEffect.
statusDelayable instance. See the How methods affect status, and vice-versa section for more information.executionseffect has been executed.timeelapsed and remaining. Both keys' values are millsecond values (Number), and they indicate the time elapsed since the last execution of the effect and the time remaining until the next execution.progress0 and 1 indicating the time progress toward the next execution of the effect.setEffect(effect)effecttimestamp parameter (see the Construct a Delayable instance section for a refresher on that parameter).Delayable instancedelay()Delays the execution(s) of the effect.
If you call delay while the effect is currently being delayed, it will start over from the beginning (and reset executions, time.elapsed, and progress to 0).
Can't be called until the DOM is available.
Delayable instancepause()Delayable instanceseek(progress)Seeks to a specific time progress in the delay. If status is playing or reversing, the animation will continue progressing in the same direction after seeking to the time progress.
If your effect is supposed to execute more than one time, you can pass a time progress that is greater than 1 to seek to a specific execution. For example, to seek halfway through the third delay, you can call seek(2.5). Your effect will instantly be executed twice, and will be halfway toward the third execution.
Can't be called until the DOM is available.
seek Accepts one parameter: a time progress to seek toDelayable instance.resume()status is anything other than paused or sought. Can't be called until the DOM is available.Delayable instancestop()Delayable instance.How methods affect status, and vice-versa
Each Delayable instance maintains a status property that allows it to take appropriate action based on the methods you call, in what order you call them, and when you call them.
At any given time, status will always be one (and only one) of the following values:
readydelayingdelayedpausedsoughtstopped
There's a lot of complexity involved in the way each status is achieved (it's affected by which methods you call,in what order you call them, and exactly when you call them), but you likely will never need to worry about that. status is available to you if you feel you need it, but for all intended use cases, it's an implementation detail, and you can ignore it.
The only thing you may want to be aware of is how status affects your ability to call certain methods—some methods can be called at any time, and some can only be called when status has a specific value.
The table below has a full breakdown:
status is...setEffectdelaypausedelayingseekresumepaused or soughtstopOr, just remember:
- If you
delaywhile the animation is already delaying, the delay will start over from the beginning (and resetexecutions,time.elapsed, andprogressto0). - You can only
pausewhile the delay process is in progress - You can
setEffect,seek, andstopat any time. Just remember thatsetEffectwill alwaysstopthe delay, and if you callseekwhile a delay is progressing, the animation will continue delaying after it seeks to the time progress you specified. - You can only
resumeafter callingpauseorseek
Using with TypeScript
Nothing special to know about using Delayable with TypeScript 🚀
API design compliance
options object.effectsetEffectset<Property> methodsstatus, executions, time, progressdelay, pause, seek, resume, stopstop methodable