Create sync/async APIs with usable logic.
Quantum + Sync - "Superposition" between sync and async.
- Typesafe
- ESM, modern JavaScript
- Zero dependencies
Heavily inspired by genasync by @loganfsmyth.
Why & How
Please refer to Anthony's blog post: Async, Sync, in Between.
Usage
import fs from 'node:fs' import { quansync } from 'quansync' // Create a quansync function by providing `sync` and `async` implementations const readFile = quansync({ sync: (path: string) => fs.readFileSync(path), async: (path: string) => fs.promises.readFile(path), }) // Create a quansync function by providing a generator function const myFunction = quansync(function* (filename) { // Use `yield*` to call another quansync function const code = yield* readFile(filename, 'utf8') return `// some custom prefix\n${code}` }) // Use it as a sync function const result = myFunction.sync('./some-file.js') // Use it as an async function const asyncResult = await myFunction.async('./some-file.js')
getIsAsync
Returns a boolean indicating whether the current execution is in async mode.
import { getIsAsync, quansync } from 'quansync' const fn = quansync(function* () { const isAsync: boolean = yield* getIsAsync() console.log(isAsync) }) fn.sync() // false await fn() // true await fn.async() // true
all
import { all, quansync } from 'quansync' const loadFiles = quansync(function* () { return yield* all([ readFile('./one.js'), readFile('./two.js'), readFile('./three.js'), ]) }) const results = loadFiles.sync() const asyncResults = await loadFiles.async()
Build-time Macro
If you don't like the function* and yield* syntax, we also provide a build-time macro via unplugin-quansync allowing you use quansync with async/await syntax, while still able to get the sync version out of that.
Here is an example:
import fs from 'node:fs' import { quansync } from 'quansync/macro' // Create a quansync function by providing `sync` and `async` implementations const readFile = quansync({ sync: (path: string) => fs.readFileSync(path), async: (path: string) => fs.promises.readFile(path), }) // Create a quansync function by providing an **async** function const myFunction = quansync(async (filename) => { // Use `await` to call another quansync function const code = await readFile(filename, 'utf8') return `// some custom prefix\n${code}` }) // Use it as a sync function const result = myFunction.sync('./some-file.js') // Use it as an async function const asyncResult = await myFunction.async('./some-file.js')
For more details on usage, refer to unplugin-quansync's docs.
Benchmark
Run the following command to benchmark the performance of quansync:
pnpm run build && pnpm run benchmarkBenchmark results indicate that each yield incurs an overhead of
approximately 150 ns, comparable to that of await sync(). (On Apple M1 Max)
Sponsors
License
MIT License © Anthony Fu and Kevin Deng