Signature: spawn<T>(fn: () => T): Promise<T> — imported from perry/thread.
Runs a closure on a new OS thread and returns a Promise that resolves when the thread completes. The main thread continues immediately — UI and other work are not blocked.
{{#include ../../examples/runtime/thread_snippets.ts:spawn-basic}}spawn returns immediately. The main thread doesn't wait:
{{#include ../../examples/runtime/thread_snippets.ts:spawn-non-blocking}}Output:
1. Starting background work
2. Main thread continues immediately
3. Got result: <computed value>
Spawn multiple tasks and they run truly concurrently — one OS thread per spawn call:
{{#include ../../examples/runtime/thread_snippets.ts:spawn-multiple}}Unlike Node.js worker_threads, each spawn is a lightweight OS thread (~8MB stack), not a full V8 isolate (~2MB heap + startup cost).
Like parallelMap, spawn closures can capture outer variables. They are deep-copied to the background thread:
{{#include ../../examples/runtime/thread_snippets.ts:spawn-capture}}Mutable variables cannot be captured — this is enforced at compile time.
spawn can return any value type. Complex values (objects, arrays, strings) are serialized back to the main thread automatically:
{{#include ../../examples/runtime/thread_snippets.ts:spawn-complex-return}}spawn is ideal for keeping native UIs responsive during heavy computation:
{{#include ../../examples/ui/threading/snippets.ts:ui-spawn-analyze}}Without spawn, the analysis would freeze the UI. With spawn, the user can still scroll, tap other buttons, or navigate while the computation runs.
// ── Node.js: ~15 lines, separate file needed ──────────
// worker.js
const { parentPort, workerData } = require("worker_threads");
const result = heavyComputation(workerData);
parentPort.postMessage(result);
// main.js
const { Worker } = require("worker_threads");
const worker = new Worker("./worker.js", {
workerData: inputData,
});
worker.on("message", (result) => {
console.log(result);
});
worker.on("error", (err) => { /* handle */ });
// ── Perry: 1 line ─────────────────────────────────────
// const result = await spawn(() => heavyComputation(inputData));No separate files. No message ports. No event handlers. No structured clone. One line.
{{#include ../../examples/runtime/thread_snippets.ts:spawn-bg-file}}{{#include ../../examples/runtime/thread_snippets.ts:spawn-api-then-process}}{{#include ../../examples/runtime/thread_snippets.ts:spawn-deferred}}