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

thready-js

v1.3.0

Published

A lightweight, type-safe thread pool manager for JavaScript and TypeScript. Bring your own worker - we handle the pooling.

Readme

🧵 Thready

A lightweight, type-safe thread pool implementation for JavaScript and TypeScript that enables true multithreading using Web Workers.

Note: Thready is a worker pool manager only. You provide your own worker script with your custom logic.

npm version License: ISC

Features

  • Simple API - Easy to use singleton pattern for quick integration
  • 🔄 Worker Pooling - Efficiently reuses worker threads instead of creating new ones
  • 📦 Zero Dependencies - No external dependencies, just pure JavaScript
  • 💪 TypeScript Support - Full type definitions included
  • Performance - Supports transferable objects for zero-copy data transfer
  • 🎯 Smart Queue Management - Automatically manages task queuing and load balancing
  • 🔍 Statistics - Built-in monitoring of pool state and performance
  • 🎨 Bring Your Own Worker - You write the worker logic, we handle the pooling

Installation

npm install thready-js

or with yarn:

yarn add thready-js

Quick Start

1. Initialize Thready in Your Project

Run the following command to generate configuration and worker template files:

npx thready init

This creates a thready-js/ folder with:

  • thready.config.js - Pre-configured thready instance
  • thready.worker.mjs - Node.js worker template
  • thready.worker.js - Browser worker template

2. Customize Your Worker

Edit thready-js/thready.worker.mjs (or .js for browser) to add your custom task handlers:

// thready-js/thready.worker.mjs
import { parentPort } from 'worker_threads';

if (!parentPort) {
  throw new Error('This script must be run as a worker thread');
}

parentPort.on('message', (message) => {
  const { id, taskType, payload } = message;
  
  try {
    let result;
    
    // Add your custom task handlers here
    switch (taskType) {
      case 'fibonacci':
        result = fibonacci(payload);
        break;
      case 'processData':
        result = processData(payload);
        break;
      default:
        throw new Error(\`Unknown task type: \${taskType}\`);
    }
    
    parentPort.postMessage({ id, type: 'result', payload: result });
  } catch (error) {
    parentPort.postMessage({ id, type: 'error', payload: error.message });
  }
});

function fibonacci(n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

function processData(data) {
  // Your heavy computation here
  return data.map(x => x * 2);
}

3. Use Thready in Your Application

Simply import the pre-configured instance and start executing tasks:

import thready from './thready-js/thready.config.js';

// Execute tasks - thready is already initialized!
async function calculate() {
  try {
    const result = await thready.execute('fibonacci', 40);
    console.log('Result:', result);
  } catch (error) {
    console.error('Task failed:', error);
  }
}

// Cleanup on shutdown
process.on('SIGINT', () => {
  thready.shutdown();
  process.exit(0);
});

That's it! No manual initialization needed - just import and use.

Advanced Usage

Customizing Configuration

Edit thready-js/thready.config.js to customize worker count or worker path:

// thready-js/thready.config.js
import thready from 'thready-js';
import { Worker } from 'worker_threads';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Initialize with custom settings
thready.init({
  maxWorkers: 8, // Increase worker count
  worker: () => new Worker(join(__dirname, './thready.worker.mjs'), { type: 'module' }),
});

export default thready;

Using with Vite or Webpack

For browser environments, update the config to use Web Workers:

// thready-js/thready.config.js
import thready from 'thready-js';

// Vite/Webpack
thready.init({
  maxWorkers: 4,
  worker: () => new Worker(new URL('./thready.worker.js', import.meta.url), { type: 'module' })
});

export default thready;

Transferable Objects (Zero-Copy)

For better performance with large data, use transferables:

import thready from './thready-js/thready.config.js';

async function processImage(imageData) {
  const buffer = imageData.buffer;
  
  // Transfer ownership of the buffer (zero-copy)
  const result = await thready.execute(
    'processImage',
    buffer,
    [buffer] // Transferables array
  );
  
  return result;
}

Direct API Usage (Advanced)

If you prefer manual control, you can import threadPool directly:

import { threadPool } from 'thready-js';
import { Worker } from 'worker_threads';

// Manual initialization
threadPool.init({
  maxWorkers: 4,
  worker: () => new Worker('./custom-worker.mjs')
});

const result = await threadPool.execute('taskType', payload);
import { WorkerPool } from 'thready';
### Using WorkerPool Directly

For even more control, use the `WorkerPool` class:

```javascript
import { WorkerPool } from 'thready-js';
import { Worker } from 'worker_threads';

const pool = new WorkerPool({
  maxWorkers: 8,
  worker: () => new Worker('./worker.mjs')
});

const result = await pool.run('taskType', payload);

// Get statistics
const stats = pool.getStats();
console.log(stats);
// {
//   totalWorkers: 8,
//   availableWorkers: 6,
//   activeTasks: 2,
//   queuedTasks: 0
// }

// Cleanup
pool.terminate();

Monitoring Pool Statistics

import thready from './thready-js/thready.config.js';

const stats = thready.getStats();
console.log('Pool status:', stats);
// {
//   totalWorkers: 4,
//   availableWorkers: 2,
//   activeTasks: 2,
//   queuedTasks: 5
// }

Framework Examples

React

import thready from './thready-js/thready.config.js';
import { useEffect, useState } from 'react';

function App() {
  const [result, setResult] = useState(null);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    // Cleanup on unmount
    return () => thready.shutdown();
  }, []);

  const handleCalculate = async () => {
    setLoading(true);
    try {
      const res = await thready.execute('fibonacci', 40);
      setResult(res);
    } catch (error) {
      console.error(error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <button onClick={handleCalculate} disabled={loading}>
        {loading ? 'Calculating...' : 'Calculate Fibonacci'}
      </button>
      {result && <p>Result: {result}</p>}
    </div>
  );
}

Node.js with Worker Threads

The generated thready-js/thready.worker.mjs is already set up for Node.js worker_threads. Just add your task handlers and use it:

// index.js
import thready from './thready-js/thready.config.js';

async function main() {
  const result = await thready.execute('fibonacci', 35);
  console.log('Result:', result);
  
  thready.shutdown();
}

main();

API Reference

CLI Commands

  • npx thready init - Generate configuration and worker template files in thready-js/ folder

thready (Default Export)

The pre-configured singleton instance from thready-js/thready.config.js.

Methods

  • execute<T>(taskType: string, payload: any, transferables?: Transferable[]): Promise<T>

    Executes a task on the thread pool.

    • taskType: Identifier for the type of work
    • payload: Data to be processed
    • transferables (optional): Array of transferable objects
    • Returns: Promise resolving to the result
  • getStats(): object | null

    Returns current pool statistics.

  • shutdown(): void

    Terminates all workers and releases resources.

threadPool (Named Export - Advanced)

The singleton instance for manual initialization.

Methods

  • init(config: WorkerPoolConfig): void

    Initializes the thread pool with your worker implementation.

    • config.maxWorkers (optional): Maximum number of workers (defaults to CPU cores)
    • config.worker: Path to worker script or factory function that returns a Worker
  • execute<T>(taskType: string, payload: any, transferables?: Transferable[]): Promise<T>

  • getStats(): object | null

  • shutdown(): void

WorkerPool

The underlying pool implementation for direct usage.

Constructor

new WorkerPool(config: WorkerPoolConfig)

Methods

  • run<T>(taskType: string, payload: any, transferables?: Transferable[]): Promise<T>
  • getStats(): object
  • terminate(): void

TypeScript

Full TypeScript support with exported types:

import thready from './thready-js/thready.config.js';
import type { 
  WorkerPoolConfig,
  WorkerMessage,
  WorkerResponse,
  Task
} from 'thready-js';

// Custom typed execution
interface CalculationResult {
  value: number;
  duration: number;
}

const result = await thready.execute<CalculationResult>('calculate', { n: 100 });

Best Practices

  1. Run npx thready init: Start with generated templates for quick setup
  2. Customize Workers: Edit thready-js/thready.worker.mjs (or .js) with your task handlers
  3. Import Config: Use import thready from './thready-js/thready.config.js' - already initialized
  4. Cleanup: Always call thready.shutdown() when your application closes
  5. Transferables: Use transferables for large data (ArrayBuffers, ImageData) to avoid copying
  6. Error Handling: Always wrap execute() calls in try-catch blocks
  7. Task Granularity: Break large tasks into smaller chunks for better load balancing

Performance Tips

  • Use transferables for data > 1MB
  • Adjust maxWorkers in thready-js/thready.config.js to match your workload
  • Monitor stats with thready.getStats() to tune pool size
  • Reuse the same worker script for multiple task types
  • Keep worker scripts focused and pure

Browser Support

Works in all modern browsers that support Web Workers:

  • Chrome 4+
  • Firefox 3.5+
  • Safari 4+
  • Edge (all versions)

License

ISC © Ram Krishna Yadav

Contributing

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

Issues

Found a bug or have a feature request? Open an issue

Links