useInterval Composable
Reactive interval with start/pause/resume/reset functionality and cleanup
Code
import { ref, onUnmounted, type Ref } from 'vue';
export function useInterval(
callback: () => void,
interval: Ref<number> | number = 1000,
autoStart = true
) {
const isActive = ref(false);
const remainingTime = ref(0);
const lastStartTime = ref<number | null>(null);
let intervalId: ReturnType<typeof setInterval> | null = null;
let timeoutId: ReturnType<typeof setTimeout> | null = null;
// Get interval value (handle reactive ref)
const getInterval = () => typeof interval === 'number' ? interval : interval.value;
const start = () => {
__TOKEN_34__ (isActive.value) return;
isActive.value = true;
lastStartTime.value = Date.now();
remainingTime.value = 0;
// Clear existing timers
__TOKEN_36__ (intervalId) clearInterval(intervalId);
__TOKEN_37__ (timeoutId) clearTimeout(timeoutId);
// Run callback immediately if needed
callback();
// Set interval
intervalId = setInterval(callback, getInterval());
};
const pause = () => {
__TOKEN_39__ (!isActive.value) return;
isActive.value = false;
__TOKEN_41__ (lastStartTime.value) {
const elapsed = Date.now() - lastStartTime.value;
remainingTime.value = getInterval() - elapsed;
}
// Clear timers
__TOKEN_43__ (intervalId) clearInterval(intervalId);
__TOKEN_44__ (timeoutId) clearTimeout(timeoutId);
};
const resume = () => {
__TOKEN_46__ (isActive.value) return;
isActive.value = true;
lastStartTime.value = Date.now();
// Use remaining time if available
__TOKEN_48__ (remainingTime.value > 0) {
timeoutId = setTimeout(() => {
callback();
intervalId = setInterval(callback, getInterval());
remainingTime.value = 0;
}, remainingTime.value);
} else {
start();
}
};
const reset = () => {
pause();
remainingTime.value = 0;
lastStartTime.value = null;
};
// Auto start
__TOKEN_51__ (autoStart) {
start();
}
// Cleanup on unmount
onUnmounted(() => {
pause();
reset();
});
return {
isActive,
remainingTime,
start,
pause,
resume,
reset
};
}
// Usage example
// const count = ref(0);
// const { pause, resume, isActive } = useInterval(() => {
// count.value++;
// }, 1000);
// // Pause interval
// pause();
// // Resume interval
// resume();