Table of Contents
About The Project
Scheduling events in the browser can be challenging. Timeouts you set may be delayed by other tasks running on the main thread. Switching tabs or resizing the window can further impact accuracy, as the main thread gets throttled by the browser. This becomes especially noticeable when events are scheduled to fire in sequence, as the delay will accumulate.
In contrast, web workers run on a separate thread in the background, independent of intensive computations on the main thread, and are not throttled by the browser. However, they are notoriously challenging to use since the only way to communicate with them is through messages sent between the threads.
This package aims to address this issue by providing a convenient React hook for scheduling events in a web worker, while abstracting away some of the complexities of working with them directly.
To use the hook, you define a list of checkpoints and a callback that is called whenever a checkpoint is reached. It returns a set of functions to control the playback of these checkpoints, including playing, pausing, navigating to a specific point in the playback, and looping. Additionally, it provides the current state of the playback and an estimated progress based on the elapsed time since the last reported checkpoint.
Built With
Getting Started
Prerequisites
- React
- npm or deno
Installation
Deno
import { usePlayback } from "https://deno.land/x/use_worker_timer/index.ts"
NPM
npm install use-worker-timer
import { usePlayback } from "use-worker-timer"
Usage
To use this hook, you pass in a list of checkpoints, as ms values, and a callback that is called whenever a checkpoint is reached. The hook will return a bunch of functions to control the playback, as well as the current state of the playback.
// Creates a list of 64 events, with a spacing of 60 bpm
const BPM = 60
const checkpoints = Array.from({ length: 4 * 16 }).map((_, i) => (i * (60 * 1000)) / BPM)
const callbackForTime = (ms: number) => {
console.log(`Reached checkpoint ${reportedTime}`)
if(i === events.length - 1){
console.log("Reached the end!")
}
}
...
const {
isReady, // Wether the worker is ready to start playing
playState, // The state of the playback as reported by the worker
estimatedProgress, // The estimated progress, based on the last reported checkpoint
lagLog, // A log of the inaccuracy of the timer
play,
pause,
stop,
setLooping,
setPlaybackProgress,
} = usePlayback({
reportCheckpoint: callbackForTime,
checkpoints: checkpoints,
estimationUpdateInterval: 100, // How often to update the estimated progress
})
Arguments
reportCheckpoint
is called whenever a checkpoint is reached.checkpoints
is a list of ms values, at which the worker will fire thereportCheckpoint
callback.estimationUpdateInterval
is how often the estimated progress will be updated. Defaults to never (always same asplayState.progress
). If omitted, the estimated progress will be the same as in playState.
Return values
isReady
is a boolean that is true when the worker is ready to start playing.playState
will update whenever a checkpoint is reached or a playback function is called. It is an object with the following properties:playing
is a boolean that is true when the worker is playing.progress
is the progress of the playback, in ms.looping
is a boolean that is true when the worker is looping.
estimatedProgress
will update everyestimationUpdateInterval
milliseconds, and is based on the last reported checkpoint. As this is calculated on the main thread, it might be slightly off. I recommend using it for UI, but use the reported checkpoints for logic.lagLog
is an array of numbers, that represent the inaccuracy of the timer. It will be filled with the inaccuracy per checkpoint, in ms, whenever a checkpoint is reached.play
,pause
,stop
,setLooping
andsetPlaybackProgress
are functions that control the playback. Self explanatory.
Take a look at the full example (source).
License
Licensed under no license, do whatever you want with this, why would I care.
Contact
PetrosiliusPatter - PetrosiliusPatter@proton.me
Project Link: https://github.com/PetrosiliusPatter/use-worker-timer