bun-threads is a lightweight, developer-friendly TypeScript library for Bun that makes it effortless to offload tasks into separate worker threads. It wraps worker threads and messaging with a clean, promise-based interface and type support, enabling easy parallel processing without any boilerplate or separate worker files. bun-threads makes writing multithreaded JavaScript and TypeScript feel more like writing the asynchronous single threaded code that you are used to.
Simple API: Create and run worker threads easily using the Thread and ThreadPool classes.
Type-Safe: Written in pure Typescript. Arguments and return values are automatically typed.
Automatic Scaling: Manage thread lifecycle and scaling without verbose setup code.
Low Config: Works out of the box. No setup files or separate worker files required.
Tested: Uses native bun:test library to ensure proper coverage and code quality.
File | % Funcs | % Lines | Uncovered Line #s |
---|---|---|---|
All files | 93.83 | 99.01 | |
thread.ts | 92.00 | 99.04 | |
threadpool.ts | 95.65 | 98.99 |
51 pass
0 fail
97 expect() calls
Ran 51 tests across 1 files. [744.00ms]
bun add bun-threads
Thread.close()
or ThreadPool.close()
method when you are done with the instance. Instances of Thread close themselves by default after completing all of their queued run()
calls if no idleTimeout
was specified or if idleTimeout
is set to 0. Instances of ThreadPool keep at least minThreads
number of Threads open by default for faster startup times on subsequent run()
calls. Setting an instance of ThreadPool's minThreads
to 0 will also cause all of it's underlying Thread instances to close themselves after completing each run()
call, similar to how an instance of a single Thread behaves.run()
call. Even if your callback function doesn't have any arguments, you still must pass an empty array. This is required by TypeScript to infer the types of your arguments to provide IntelliSense and code completion.// incorrect example:
import { availableParallelism } from "os";
const badThread = new Thread(() => {
console.log(availableParallelism())
})
badThread.run() // throws ReferenceError: availableParallelism is not defined
// correct example:
const goodThread = new Thread(async () => {
const os = await import("os")
console.log(os.availableParallelism())
})
goodThread.run() // works correctly
import { Thread } from "bun-threads";
const proof = new Thread(() => Bun.isMainThread)
console.log('Thread isMainThread:', await proof.run([])) // no arguments so pass an empty array
console.log('Main process isMainThread:', Bun.isMainThread)
import { Thread } from "bun-threads";
const addThread = new Thread((a: number, b: number) => {
return a + b
})
addThread.run([21, 21]).then((result) => console.log(result))
import { Thread, ThreadPool } from "bun-threads";
const thread = new Thread((wait: number) => Bun.sleepSync(wait)) // simulate some synchronous work
const threadPool = new ThreadPool((wait: number) => Bun.sleepSync(wait)) // simulate some synchronous work
let start = performance.now()
await Promise.all([,
thread.run([1_000]),
thread.run([1_000]),
thread.run([1_000])
])
// a single Thread can only execute synchronous tasks one at a time
console.log('Thread completed in:', performance.now() - start, 'ms') // ~ 3000 ms
start = performance.now()
await Promise.all([,
threadPool.run([1_000]),
threadPool.run([1_000]),
threadPool.run([1_000])
])
// ThreadPool runs each task in a separate Thread in parallel
console.log('ThreadPool completed in:', performance.now() - start, 'ms') // ~ 1000 ms
thread.close()
threadPool.close()