Abstractions around Bun workers to enable working with them as promises.
npm install bun-threads- 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.02 |
thread.ts | 92.00 | 99.06 |
threadpool.ts | 95.65 | 98.99 |
---------------|---------|---------|-------------------
51 pass
0 fail
100 expect() calls
Ran 51 tests across 1 file. [1233.00ms]
bash
bun add bun-threads
`โ FAQ
$3
- They're great projects, but they either don't work properly in Bun (workerpool is almost there), or they require that you to create a separate worker file, which is something that this library aims to avoid.$3
- Currently this library is using one small Bun specific API and Bun's implementation of Node's Worker API. Using Bun's actual native Worker API is planned for the future, but as it's still experimental, it has a few bugs in it that make it unfeasible to use at the moment. Once the native Bun Worker API stabilizes, a full switchover to the native API will be made to take advantage of the performance gains.$3
- Make sure that you are calling the 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.$3
- Check your imports. Worker threads don't have access to your top level imports at the top of your file. Instead, use dynamic imports inside of your thread's callback function.
`ts
// 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
`Examples
$3
`ts
import { Thread } from "bun-threads";const proof = new Thread(() => Bun.isMainThread)
console.log('Thread isMainThread:', await proof.run())
console.log('Main process isMainThread:', Bun.isMainThread)
`$3
`ts
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))
`$3
`ts
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()
`Changelog
$3
- Fixed nested promises in `Thread.run()` and `ThreadPool.run()` return types. Example: Both methods will now return `Promise` instead of `Promise> ``.