npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

shared-timer-manager

v1.0.3

Published

Manage multiple timer tasks with a single SharedWebWorker

Readme

Shared Timer Manager

Manage multiple timer tasks with a single SharedWebWorker. Perfect for handling recurring tasks like token refresh, inactivity detection, and sleep mode across your application.

Features

  • Single SharedWebWorker - All timers run in one worker, reducing overhead
  • Named Task Management - Easy to manage with unique task identifiers
  • Repeating & One-time Tasks - Flexible timer control
  • Cross-tab Synchronization - Shared timers across browser tabs
  • TypeScript Support - Full type definitions included
  • Zero Dependencies - Lightweight and fast
  • Framework Agnostic - Works with React, Vue, Angular, Svelte, and vanilla JS

Why use a SharedWorker for precise timing

Using a SharedWorker for scheduling time-sensitive tasks is often preferable to relying on setInterval/setTimeout on the main thread:

  • Runs off the main thread: timers in a SharedWorker are not blocked by main-thread work (UI rendering, long-running scripts), which reduces jitter and missed ticks.
  • Less affected by event-loop blocking: main-thread timers pause or drift when the event loop is busy; a worker provides an isolated execution context so scheduled tasks execute more reliably.
  • Cross-tab single source of truth: a SharedWorker can serve multiple tabs/windows, avoiding duplicated timers and reducing cumulative drift when the same task would otherwise run in many contexts.
  • Resource-efficient: centralizing timers avoids redundant timers across contexts and reduces overall CPU usage.
  • Background behavior: while browsers may throttle background activity, a SharedWorker centralizes coordination so connectivity-dependent tasks (e.g., token refresh) remain consistent across open pages.

Installation

npm install shared-timer-manager

Quick Start

1. Copy the worker file to your public directory

cp node_modules/shared-timer-manager/dist/shared-timer-worker.js public/

2. Use in your application

import TimerManager from 'shared-timer-manager';

// Initialize
const timerManager = new TimerManager('/shared-timer-worker.js');

// Add a repeating task
timerManager.addTimerTask(
  'token-refresh',
  15 * 60 * 1000, // 15 minutes
  () => {
    console.log('Refreshing token...');
    refreshToken();
  },
  true // repeats
);

// Add a one-time task
timerManager.addTimerTask(
  'inactivity-logout',
  5 * 60 * 1000, // 5 minutes
  () => {
    console.log('Logging out due to inactivity');
    logout();
  },
  false // doesn't repeat
);

// Clear a specific task
timerManager.clearTimerTask('token-refresh');

// Remove all tasks
timerManager.removeAllTimerTasks();

API Reference

Constructor

new TimerManager(workerPath)

Creates a new TimerManager instance.

Parameters:

  • workerPath (string, optional): Path to the shared worker file. Default: '/shared-timer-worker.js'

Example:

const timerManager = new TimerManager('/workers/shared-timer-worker.js');

Methods

addTimerTask(taskName, intervalTime, callback, canRepeat)

Adds a new timer task.

Parameters:

  • taskName (string): Unique identifier for the task
  • intervalTime (number): Interval in milliseconds
  • callback (function): Function to execute on each interval. Receives (taskName, timestamp) as arguments
  • canRepeat (boolean, optional): Whether the task should repeat. Default: true

Example:

timerManager.addTimerTask('my-task', 5000, (name, timestamp) => {
  console.log(`${name} executed at ${timestamp}`);
}, true);

clearTimerTask(taskName)

Clears a specific timer task.

Parameters:

  • taskName (string): Name of the task to clear

Example:

timerManager.clearTimerTask('my-task');

removeAllTimerTasks()

Removes all timer tasks.

Example:

timerManager.removeAllTimerTasks();

hasTask(taskName)

Check if a task exists.

Parameters:

  • taskName (string): Name of the task

Returns:

  • boolean: Whether the task exists

Example:

if (timerManager.hasTask('token-refresh')) {
  console.log('Token refresh task is active');
}

getActiveTasks()

Get list of active task names.

Returns:

  • Array<string>: Array of active task names

Example:

const tasks = timerManager.getActiveTasks();
console.log('Active tasks:', tasks); // ['token-refresh', 'inactivity-logout']

ping(taskName)

Check if the worker is connected (health check).

Parameters:

  • taskName (string, optional): Task name for ping. Default: 'health-check'

Returns:

  • boolean: Connection status

Example:

const isConnected = timerManager.ping();

Common Use Cases

Access Token Refresh

Automatically refresh authentication tokens at regular intervals:

timerManager.addTimerTask(
  'token-refresh',
  15 * 60 * 1000, // Every 15 minutes
  async () => {
    try {
      await refreshAccessToken();
      console.log('Token refreshed successfully');
    } catch (error) {
      console.error('Token refresh failed:', error);
    }
  },
  true
);

Inactivity Logout

Log out users after a period of inactivity:

function setupInactivityTimer() {
  timerManager.addTimerTask(
    'inactivity-logout',
    5 * 60 * 1000, // 5 minutes
    () => {
      console.log('User inactive - logging out');
      logout();
    },
    false
  );
}

// Reset timer on user activity
const resetTimer = () => {
  timerManager.clearTimerTask('inactivity-logout');
  setupInactivityTimer();
};

document.addEventListener('mousemove', resetTimer);
document.addEventListener('keydown', resetTimer);
document.addEventListener('click', resetTimer);

// Initialize
setupInactivityTimer();

Sleep Mode

Reduce backend requests after inactivity:

function setupSleepMode() {
  timerManager.addTimerTask(
    'sleep-mode',
    5 * 60 * 1000, // 5 minutes
    () => {
      console.log('Activating sleep mode');
      activateSleepMode();
      // Stop non-critical API polling
      stopBackgroundSync();
    },
    false
  );
}

// Reset on user activity
const resetSleepMode = () => {
  if (timerManager.hasTask('sleep-mode')) {
    timerManager.clearTimerTask('sleep-mode');
    deactivateSleepMode();
    setupSleepMode();
  }
};

window.addEventListener('focus', resetSleepMode);
document.addEventListener('visibilitychange', () => {
  if (!document.hidden) {
    resetSleepMode();
  }
});

setupSleepMode();

Framework Integration

React

Create a custom hook for easy integration:

// hooks/useTimerManager.js
import { useEffect, useRef } from 'react';
import TimerManager from 'shared-timer-manager';

export function useTimerManager() {
  const timerManagerRef = useRef(null);

  useEffect(() => {
    timerManagerRef.current = new TimerManager('/shared-timer-worker.js');

    return () => {
      timerManagerRef.current?.removeAllTimerTasks();
    };
  }, []);

  return timerManagerRef.current;
}

// Usage in component
function App() {
  const timerManager = useTimerManager();

  useEffect(() => {
    if (timerManager) {
      timerManager.addTimerTask('token-refresh', 15 * 60 * 1000, () => {
        refreshToken();
      }, true);
    }
  }, [timerManager]);

  return <div>My App</div>;
}

Vue 3 (Composition API)

// composables/useTimerManager.js
import { onUnmounted } from 'vue';
import TimerManager from 'shared-timer-manager';

const timerManager = new TimerManager('/shared-timer-worker.js');

export function useTimerManager() {
  onUnmounted(() => {
    timerManager.removeAllTimerTasks();
  });

  return {
    addTask: (name, interval, callback, repeat = true) => 
      timerManager.addTimerTask(name, interval, callback, repeat),
    clearTask: (name) => timerManager.clearTimerTask(name),
    removeAll: () => timerManager.removeAllTimerTasks(),
    hasTask: (name) => timerManager.hasTask(name),
    getActiveTasks: () => timerManager.getActiveTasks()
  };
}

// Usage in component
<script setup>
import { onMounted } from 'vue';
import { useTimerManager } from '@/composables/useTimerManager';

const { addTask, clearTask } = useTimerManager();

onMounted(() => {
  addTask('token-refresh', 15 * 60 * 1000, () => {
    console.log('Refreshing token...');
  });
});
</script>

Angular

// services/timer-manager.service.ts
import { Injectable, OnDestroy } from '@angular/core';
import TimerManager from 'shared-timer-manager';

@Injectable({
  providedIn: 'root'
})
export class TimerManagerService implements OnDestroy {
  private timerManager: TimerManager;

  constructor() {
    this.timerManager = new TimerManager('/shared-timer-worker.js');
  }

  addTask(name: string, interval: number, callback: Function, repeat = true): void {
    this.timerManager.addTimerTask(name, interval, callback as any, repeat);
  }

  clearTask(name: string): void {
    this.timerManager.clearTimerTask(name);
  }

  removeAllTasks(): void {
    this.timerManager.removeAllTimerTasks();
  }

  hasTask(name: string): boolean {
    return this.timerManager.hasTask(name);
  }

  getActiveTasks(): string[] {
    return this.timerManager.getActiveTasks();
  }

  ngOnDestroy(): void {
    this.timerManager.removeAllTimerTasks();
  }
}

// Usage in component
export class AppComponent {
  constructor(private timerService: TimerManagerService) {
    this.timerService.addTask('token-refresh', 15 * 60 * 1000, () => {
      console.log('Refreshing token...');
    }, true);
  }
}

Svelte

// stores/timerStore.js
import { onDestroy } from 'svelte';
import TimerManager from 'shared-timer-manager';

const timerManager = new TimerManager('/shared-timer-worker.js');

export function useTimer() {
  onDestroy(() => {
    timerManager.removeAllTimerTasks();
  });

  return timerManager;
}

// Usage in component
<script>
  import { onMount } from 'svelte';
  import { useTimer } from './stores/timerStore';
  
  const timer = useTimer();
  
  onMount(() => {
    timer.addTimerTask('my-task', 5000, () => {
      console.log('Timer tick!');
    }, true);
  });
</script>

Vanilla JavaScript

import TimerManager from 'shared-timer-manager';

const timerManager = new TimerManager('/shared-timer-worker.js');

// Add tasks
timerManager.addTimerTask('periodic-sync', 30000, () => {
  syncData();
}, true);

// Clear when needed
document.getElementById('stop-btn').addEventListener('click', () => {
  timerManager.clearTimerTask('periodic-sync');
});

Browser Support

SharedWebWorker is supported in:

  • ✅ Chrome/Edge 4+
  • ✅ Firefox 29+
  • ✅ Safari 16+
  • ❌ Internet Explorer (not supported)

Note: For browsers that don't support SharedWebWorker, consider implementing a fallback using regular setInterval or Web Workers.


TypeScript Support

This package includes TypeScript definitions. No additional types package needed!

import TimerManager from 'shared-timer-manager';

const timerManager: TimerManager = new TimerManager('/shared-timer-worker.js');

timerManager.addTimerTask(
  'my-task',
  5000,
  (taskName: string, timestamp: number) => {
    console.log(`Task ${taskName} executed at ${timestamp}`);
  },
  true
);

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

MIT © [Dario Espina]


Support

If you encounter any issues or have questions:


Changelog

1.0.0

  • Initial release
  • Support for multiple timer tasks with single SharedWebWorker
  • Cross-tab synchronization
  • TypeScript support
  • Framework-agnostic implementation