promise-worker-ts
v0.0.1
Published
Type-safe Promise-based Web Worker communication with TypeScript, supporting tagged messages and transferable objects
Maintainers
Readme
promise-worker-ts 🚀
Type-safe Promise-based communication with Web Workers in TypeScript.
Features ✨
- 🔒 Fully Type-Safe: Complete end-to-end type safety for Web Worker communication
- 🏷️ Tagged Messages: Support for multiple message types in a single worker
- 🔄 Promise-Based: Clean, modern async/await syntax
- 📦 Zero Dependencies: Lightweight and framework-agnostic
- 🛡️ TypeScript First: Built with TypeScript for the best developer experience
- 📤 Transferable Objects: Full support for transferring ownership of objects between threads
Installation 📦
npm install promise-worker-ts
# or
yarn add promise-worker-ts
# or
pnpm add promise-worker-tsQuick Start 🚀
Basic Usage
- Define your shared types (e.g.,
types.shared.ts):
import type { PromiseWorker } from "promise-worker-ts";
export type DoubleNumber = PromiseWorker<number, number>;- Set up your worker (
worker.ts):
import { listen } from "promise-worker-ts";
import type { DoubleNumber } from "./types.shared";
listen<DoubleNumber>((num) => num * 2);- Use in your main thread:
import { send } from "promise-worker-ts";
import type { DoubleNumber } from "./types.shared";
const worker = new Worker(/* ... */);
const result = await send<DoubleNumber>(worker, 21); // result = 42Tagged Messages
When you need multiple message types in a single worker:
- Define tagged types:
import type { PromiseWorkerTagged } from "promise-worker-ts";
export type AddNumbers = PromiseWorkerTagged<"add", [number, number], number>;
export type MultiplyNumbers = PromiseWorkerTagged<
"multiply",
[number, number],
number
>;- Set up worker handlers:
import { listen } from "promise-worker-ts";
import type { AddNumbers, MultiplyNumbers } from "./types.shared";
listen<AddNumbers>("add", ([a, b]) => a + b);
listen<MultiplyNumbers>("multiply", ([a, b]) => a * b);- Use in main thread:
import { send } from "promise-worker-ts";
import type { AddNumbers, MultiplyNumbers } from "./types.shared";
const worker = new Worker("worker.ts");
const sum = await send<AddNumbers>("add", worker, [5, 3]); // 8
const product = await send<MultiplyNumbers>("multiply", worker, [5, 3]); // 15API Reference 📖
Types
These types are technically objects, but they're convenience types for being able to define once and use in both workers and main thread.
PromiseWorker<Input, Output, Error = unknown>
Basic type for single-purpose workers
Input: Type of data sent to workerOutput: Type of data received from workerError: Optional error type
PromiseWorkerTagged<Tag, Input, Output, Error = unknown>
Type for tagged messages in multi-purpose workers
Tag: Literal string type for message identificationInput: Type of data sent to workerOutput: Type of data received from workerError: Optional error type
Functions
send<T>(worker: Worker, input: Input): Promise<Output>
Send message to untagged worker
send<T>(tag: string, worker: Worker, input: Input): Promise<Output>
Send message to tagged worker
listen<T>(handler: (input: Input) => Output | Promise<Output>): void
Listen for untagged messages
listen<T>(tag: string, handler: (input: Input) => Output | Promise<Output>): void
Listen for tagged messages
Advanced Usage 🔧
Error Handling
type DivideNumbers = PromiseWorkerTagged<
"divide", // Tag
[number, number], // Input
number, // Output
"Division by zero" // Error
>;
// In worker
listen<DivideNumbers>("divide", ([a, b]) => {
if (b === 0) throw "Division by zero";
return a / b;
});
// In main thread
try {
const result = await send<DivideNumbers>("divide", worker, [10, 0]);
} catch (error) {
console.error(error); // 'Division by zero'
}Transferable Objects
// Send with transferable objects
const arrayBuffer = new ArrayBuffer(1024);
await send<MyType>(worker, arrayBuffer, [arrayBuffer]);
// Send back transferable objects
listen<MyType>((arrayBuffer, transferables) => {
const newArrayBuffer = new ArrayBuffer(1024);
// Add to transfer queue and return
transferables.push(newArrayBuffer);
return newArrayBuffer;
});For listening, you can pass a callback function.
Todo
- [x] Write tests for transferable objects
- [ ] Write more robust test for passing back transfer objects
- [ ] Make it so workers can initiate promises to their parent threads
Contributing 🤝
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License 📄
This project is licensed under the MIT License - see the LICENSE file for details.
Support 💖
If you find this project helpful, please consider:
- Starring the repository ⭐
- Reporting issues 🐛
- Contributing improvements 🛠️
- Sharing with others 🌟
Credits 👏
Created and maintained by Peter Batory-Bernardin
