UNPKG

@ayonli/jsext

Version:

A JavaScript extension package for building strong and modern applications.

139 lines (138 loc) 4.54 kB
/** * Runs a script in a worker thread and invokes its `default` function to * collect the result. * @module */ /** * Options for the {@link run} function. */ export interface RunOptions { /** * If not set, invoke the `default` function, otherwise invoke the specified * function. */ fn?: string; /** Automatically abort the task when timeout (in milliseconds). */ timeout?: number; /** * Instead of dropping the worker after the task has completed, keep it * alive so that it can be reused by other tasks. */ keepAlive?: boolean; /** * Choose whether to use `worker_threads` or `child_process` for running * the script. The default setting is `worker_threads`. * * In browsers, this option is ignored and will always use the web worker. * * Always prefer `worker_threads` over `child_process` if possible, because * it is more efficient and has better performance. * * For users who use [tsx](https://www.npmjs.com/package/tsx) to run * TypeScript directly in Node.js, the runtime is unable to use TypeScript * directly in worker threads at the moment, to run TypeScript, we need to * use `child_process` adapter. * See [this issue](https://github.com/privatenumber/tsx/issues/354) for more * information. */ adapter?: "worker_threads" | "child_process"; /** * Instead of aborting the task by calling the `abort()` method manually, * we can use an `AbortSignal` to abort the task automatically when the * signal is aborted. */ signal?: AbortSignal; } /** * The return value of the {@link run} function. */ export interface WorkerTask<R> { /** * The ID of the worker thread that runs the task. */ workerId: number; /** * Retrieves the return value of the function being called. */ result(): Promise<R>; /** * Iterates the yield value if the function being called returns a generator. */ iterate(): AsyncIterable<R>; /** * Terminates the worker thread and aborts the task. If `reason` is provided, * `result()` or `iterate()` will throw that error. Otherwise, an `AbortError` * will be thrown. */ abort(reason?: any): void; } /** * Runs the given `script` in a worker thread and invokes its `default` function * to collect the result. * * This function is similar to {@link parallel}(), many features and * restrictions applicable to `parallel()` are also applicable to `run()`, * except the following: * * 1. The `script` can only be a filename, and is relative to the current * working directory (or the current URL) if not absolute. * 2. Only one task is allow to run at a time for one worker thread, set * {@link run.maxWorkers} to allow more tasks to be run at the same time if * needed. * 3. By default, the worker thread is dropped after the task settles, set * `keepAlive` option in order to reuse it. * 4. This function is not intended to be used in the browser, because it takes * a bare filename as argument, which will not be transformed to a proper URL * if the program is to be bundled. * * @example * ```ts * // result * import run from "@ayonli/jsext/run"; * * const job1 = await run("examples/worker.mjs", ["World"]); * console.log(await job1.result()); // Hello, World * ``` * * @example * ```ts * // iterate * import run from "@ayonli/jsext/run"; * * const job2 = await run<string, [string[]]>( * "examples/worker.mjs", * [["foo", "bar"]], * { fn: "sequence" } // sequence is a generator function * ); * for await (const word of job2.iterate()) { * console.log(word); * } * // output: * // foo * // bar * ``` * * @example * ```ts * // abort * import run from "@ayonli/jsext/run"; * import _try from "@ayonli/jsext/try"; * * const job3 = await run<string, [string]>("examples/worker.mjs", ["foobar"], { * fn: "takeTooLong", * }); * job3.abort(); * const [err, res] = await _try(job3.result()); * console.assert((err as DOMException)?.name === "AbortError"); * console.assert(res === undefined); * ``` */ declare function run<R, A extends any[] = any[]>(script: string | URL, args?: A, options?: RunOptions): Promise<WorkerTask<R>>; declare namespace run { /** * The maximum number of workers allowed to exist at the same time. * If not set, use the same setting as {@link parallel.maxWorkers}. */ var maxWorkers: number | undefined; } export default run;