worker-tls
Version:
worker-tls 提供了 动态Worker 功能 和 其它一些 Worker 场景下有用的工具集;让开发者可以像调用对象方法一样动态地调用Worker中的方法,也可以随时地往 Worker 中动态地添加函数 等等。
783 lines (731 loc) • 23.6 kB
TypeScript
/**
* worker 工具
*
* @remarks
* worker-tls 提供了关于worker 的一些工具,用于便捷地使用 worker
*
* @packageDocumentation
*/
import type { AnyFunction } from 'type-tls';
import dynamicWorkerCodeString from '/temp/dynamicWorkerMain.iife.js?raw';
import listenMessages_Dep from '/temp/listenMessages_Dep.iife.js?raw';
import type { Optional } from 'type-tls';
import type { PickMethod } from 'type-tls';
/**
* 转为异步的命令
* @remarks
* 函数的入参不变,返回参数都变为解决值为对应类型的 Promise
* 其它非函数的值都变为返回解决值为对应类型的 Promise 的函数
*/
export declare type AsyncCMD<Value> = Value extends AnyFunction ? AsyncFun<Value> : (() => Promise<Awaited<Value>>);
/**
* 把函数转为异步函数
*/
export declare type AsyncFun<Fun extends (...args: any) => any> = GetExecFunResultData<Fun> extends ReadableStream ? (...args: AsyncFunArgs<Fun>) => GetExecFunResultData<Fun> : (...args: AsyncFunArgs<Fun>) => Promise<GetExecFunResultData<Fun>>;
/**
* 异步函数的参数类型
*/
export declare type AsyncFunArgs<Fun extends (...args: any) => any> = Parameters<Fun> | [CallOptions<Parameters<Fun>>];
/**
* 函数的调用选项
*
* @remarks
* 用于设置 transfer
*/
export declare interface CallOptions<Args extends any[] = any[]> {
/**
* 给worker 里对应的函数传递的参数
*/
args: Args;
/**
* 设置将参数传送给 worker 时可转移的数据
*/
transfer: Transferable[];
}
/**
* 代码片段
*/
export declare type CodePart = Fun | BlobPart;
/**
* 代码块列表
*/
export declare type CodePartList = (CodePart | INamedFunction | INamedFunctionMap)[];
/**
* 代码块选项的综合定义
*/
export declare type CodePartOptions = CodePartList | INamedFunctionMap;
/**
* 打包 options 中的代码并转成 BlobPart[]
* @remarks
* 传入的所有的代码块最终会被分为以下几类:
*
* 1. `code` 和 `named` 中的所有具有名字的 函数和数据都会被挂载在 Worker 中的 `globalThis` 上,其中 名字会作为 属性名字;
*
* 2. `code` 和 `named`中的 匿名函数 以及 `iife` 中的函数 会被作为 立即调用函数在 Worker 启动时作为顶层代码被立即执行;
*
* 3. `message` 监听器会在 Worker 中接收 `message` 事件;
*
* @param options
* @param noDep - 禁止包含 创建 Worker 时所需要的其它依赖代码(环境代码)
* @returns
*/
export declare function createBlobParts(options: IWorkerCodes, noDep?: Optional<boolean>): BlobPart[];
/**
* 创建动态 Worker
*
* @param worker - worker实例
* @param name - worker中运行的js文件的url
* @param url - Worker 中所包含的初始代码
* @param code - Worker 中所包含的初始代码
* @param workerOptions - Worker 相关的选项
* @returns
*/
export declare function createDynamicWorker<Members, W extends AbstractWorker = Worker>(noCode?: undefined | null, workerOptions?: Optional<DynamicWorkerOptions<W>>): MembersToAsyncCMD<Members> & DynamicWorker<W>;
export declare function createDynamicWorker<Members, W extends AbstractWorker = Worker>(worker: W, name?: string): MembersToAsyncCMD<Members> & DynamicWorker<W>;
export declare function createDynamicWorker<Members, W extends AbstractWorker = Worker>(url: string, workerOptions?: Optional<Omit<DynamicWorkerOptions<W>, "noDep">>): MembersToAsyncCMD<Members> & DynamicWorker<W>;
export declare function createDynamicWorker<Members extends Record<string | number, any>, W extends AbstractWorker = Worker>(code: DynamicWorkerCodes<PickMethod<Members>>, workerOptions?: Optional<DynamicWorkerOptions<W>>): MembersToAsyncCMD<Members> & DynamicWorker<W>;
export declare function createDynamicWorker<Members extends Record<string | number, any>, W extends AbstractWorker = Worker>(codeOptions?: Optional<DynamicWorkerCodes<Members> | string | W>, workerOptions?: Optional<DynamicWorkerOptions<W> | string>): MembersToAsyncCMD<Members> & DynamicWorker<W>;
/**
* 创建动态 Worker 池
*
* @param workerNum - Worker池 中 workder 的个数
* @param codeOptions - Worker 中所包含的初始代码
* @param workerOptions - Worker 相关的选项
* @returns
*/
export declare function createDynamicWorkerPool<Members extends Record<string | number, any>, W extends AbstractWorker = Worker>(workerNum: number, codeOptions?: Optional<IWorkerCodes | string>, workerOptions?: Optional<DynamicWorkerOptions<W>>): MembersToAsyncCMD<Members> & DynamicWorkerPool<W>;
/**
* 生成可用于创建动态 Worker 的 url
*
* @remarks
*
* {@inheritDoc ./stringify.ts#dynamicWorkerCodeString}
*
* @param codeOptions - 往 Worker 中注入代码的配置选项
* @param noDep - 禁止包含 创建 Worker 时所需要的其它依赖代码(环境代码)
*/
export declare function createDynamicWorkerURL(codeOptions?: Optional<IWorkerCodes>, noDep?: Optional<boolean>): string;
/**
* 通过代码构建 ObjectURL
* @param codes
* @param args - 对于立即调用的函数传的参数
* @returns
*/
export declare function createObjectURLByCodes(codes: CodePart[], args?: Optional<any[]>): string;
/**
* 将一组脚本内容构造成 ObjectURL
* @param scripts - 脚本内容
* @param options - 选项
* @returns url字符串
*/
export declare function createObjectURLByContents(scripts: BlobPart[], options?: BlobPropertyBag | null): string;
/**
* 创建Worker客户端的代理
* @param client
* @returns
*/
export declare function createWorkerClientProxy<WClient extends WorkerClient<AbstractWorker>>(client: WClient): any;
/**
* 生成可用于创建 worker 的 url
* @remarks
* 打包 codeOptions 中的代码并生成可用于创建 worker 的 url
* @param codeOptions - 往 Worker 中注入代码的配置选项
* @param noDep - 禁止包含 创建 Worker 时所需要的其它依赖代码(环境代码)
* @returns
*/
export declare function createWorkerURL(codeOptions: IWorkerCodes, noDep?: Optional<boolean>): string;
/**
* 动态 Worker 给 Worker 扩展后的类型
*/
export declare type DWorker<W extends AbstractWorker> = W & {
/**
* 当前正在执行的任务数
*/
executingCount: number;
/**
* Worker的名字
*/
name: string;
/**
* Worker所属的 WorkerClient 的id
*/
clientId: number;
/**
* Worker 本身的 id
*/
id: number;
};
/**
* 动态Worker
*
* @remarks
* 动态 Worker 具备以下特点:
*
* - 往 Worker 中添加函数、全局变量 等
*
* - 调用 Worker 中的任意全局函数 或 全局变量
*
* - 像调用本地方法一样调用 Worker 里的方法
*
* - 会自动给实例自身添加快捷命令
*
* - 支持异步、流
*
* - 支持异步和流互相嵌套
*/
export declare class DynamicWorker<W extends AbstractWorker = Worker> extends WorkerClient<W> {
/**
*
* @param worker 已创建好的 worker 实例
* @param name
*/
constructor();
constructor(worker: W, name?: string);
constructor(url: string, workerOptions?: Optional<Omit<DynamicWorkerOptions<W>, "noDep">>);
constructor(code: IWorkerCodes, workerOptions?: Optional<DynamicWorkerOptions<W>>);
constructor(codeOrUrlOrWorker?: Optional<IWorkerCodes | string | W>, workerOptionsOrName?: Optional<DynamicWorkerOptions<W> | string>);
/**
* Worker 的实例
*/
worker: DWorker<W>;
/**
* 正在执行中的任务数
*/
get executingCount(): number;
/**
* 设置命令
* @remarks
* 会在Worker中添加一条命令,并且也会在实例自身上添加一个快捷命令(快捷方法 或 快捷属性)
*
* @param cmd
* @param name - 命令的命名;默认会取 `cmd.name` 作为名字;当 cmd 是字符串时,name 是必须的
* @param isProperty - 添加到实例自身的快捷命令是否作为属性;如果是 true,则会在实例自身上生成快捷属性
* @returns
*/
setCMD(cmd: string | AnyFunction, name?: Optional<string>, isProperty?: Optional<boolean>): Promise<boolean>;
/**
* 移除命令
* @remarks
* 会将 Worker 中的命令 和 自己实例上的对应快捷方法都给移除
* @param name
* @returns
*/
removeCMD(name: string): Promise<boolean>;
}
/**
* 动态 Worker 的初始配置 code
*/
export declare type DynamicWorkerCodes<Methods extends INamedFunctionMap> = Omit<IWorkerCodes, "named"> & {
named?: Optional<Methods | INamedFunctionList>;
};
export { dynamicWorkerCodeString }
/**
* 从 worker 实例创建 动态 Worker 的选项
*/
export declare interface DynamicWorkerFromInstOptions<W extends AbstractWorker = Worker> {
/**
* Worker 实例
*/
worker: W;
/**
* worker 的名字
*/
name?: string;
}
/**
* 动态 Worker 的选项
*/
export declare interface DynamicWorkerOptions<W extends AbstractWorker = Worker> {
/**
* 获取 Worker 实例的方法
* @defaultValue 默认会创建私有 Worker
*/
getWorker?: Optional<GetWorker<W>>;
/**
* worker 的名字
*/
name?: string;
/**
* 是否是不自动添加 动态 worker 依赖的环境代码
* 如果明确指定为 true,则不会包含 动态 worker 依赖的环境代码
* @defaultValue true
*/
noDep?: boolean;
}
/**
* 动态Worker池
*/
export declare class DynamicWorkerPool<W extends AbstractWorker = Worker> extends WorkerClient<W> {
/**
*
* @param workerNum - Worker池 中 workder 的个数
* @param codeOrUrl - code 选项 或 url
* @param workerOptions - Worker 相关的选项
*/
constructor(workerNum: number, codeOrUrl?: Optional<IWorkerCodes | string>, workerOptions?: Optional<DynamicWorkerOptions<W>>);
/**
* Worker 队列
*/
readonly queue: SortQueue<DWorker<W>>;
get worker(): DWorker<W>;
get executingCount(): number;
execStarted(worker: DWorker<W>, execRec: ExecRecord): void;
execEnded(worker: DWorker<W>): void;
/**
* 在指定 worker 中的执行命令
*
* @remarks
* 当 worker 中成功执行,且 this 上没有对应的成员时,则会自动新增对应的成员方法
*
* @param exec - 命令信息
* @param transfer - 传递给 Worker 的可传递对象。这些对象的所有权将被转移给 Worker,而发当前环境将不再保有所有权。
* @returns
*/
execCMDOnWorker(worker: DWorker<W>, exec: Exec, transfer?: Transferable[]): Promise<any>;
/**
* 在所有 worker 中的执行命令
*
* @remarks
* 当 worker 中成功执行,且 this 上没有对应的成员时,则会自动新增对应的成员方法
*
* @param exec - 命令信息
* @param transfer - 传递给 Worker 的可传递对象。这些对象的所有权将被转移给 Worker,而发当前环境将不再保有所有权。
* @returns
*/
allExecCMD(exec: Exec, transfer?: Transferable[]): Promise<any[]>;
/**
* 设置命令
* @remarks
* 会在Worker中添加一条命令,并且也会在实例自身上添加一个快捷命令(快捷方法 或 快捷属性)
*
* @param cmd
* @param name - 命令的命名;默认会取 `cmd.name` 作为名字;当 cmd 是字符串时,name 是必须的
* @param isProperty - 添加到实例自身的快捷命令是否作为属性;如果是 true,则会在实例自身上生成快捷属性
* @returns
*/
setCMD(cmd: string | AnyFunction, name?: Optional<string>, isProperty?: Optional<boolean>): Promise<boolean[]>;
/**
* 移除命令
* @remarks
* 会将 Worker 中的命令 和 自己实例上的对应快捷方法都给移除
* @param name
* @returns
*/
removeCMD(name: string): Promise<boolean[]>;
}
/**
* 命令执行信息
* @remarks
* 命令有两种类型:
*
* + 函数:
*
* - 执行命令就是执行函数
*
* - 执行命令的返回值就是函数的返回值
*
* + 数据:
*
* - 执行命令就是访问这个数据对象
*
* - 执行命令的返回值就这个数据本身
*/
declare interface Exec {
/**
* 被执行对象的名字
*/
name: string;
/**
* 函数式命令的参数
* @remarks
* 如果传递了该选项,则命令一定会被当作函数来处理
*/
args?: Optional<any[]>;
/**
* 函数式命令的 this 值
* @remarks
* 如果传递了该选项,则命令一定会被当作函数来处理
*/
this?: any;
}
/**
* 命令执行的记录
*/
declare interface ExecRecord extends Exec {
/**
* 本次执行的id
*/
id: string;
}
/**
* 函数 或 函数代码
*/
declare type Fun = AnyFunction | FunctionCode;
/**
* 定义函数的代码
*
* @remarks
* 可从 `fun.toString()` 得到
*/
declare type FunctionCode = string;
/**
* 提取 函数 Fun 的返回类型 ExecRes<D> 中的 D 的类型
*/
export declare type GetExecFunResultData<Fun extends (...args: any) => any> = GetExecResultData<Awaited<ReturnType<Fun>>>;
/**
* 提取 ExecRes<D> 中的 D 的类型
* @remarks
* 用于提取 ExecResult 类型中的 D 的类型
*/
export declare type GetExecResultData<ExecRes> = ExecRes extends {
data: infer D;
} ? D : ExecRes;
/**
* 获取 Worker 的回调函数
* @remarks
* 这个函数就是用来根据回调的入参创建 worker 实例的
*
* @param url - 用于创建 Worker 的 url;
* @param name - Worker 的名字
*/
export declare type GetWorker<W extends AbstractWorker = Worker> = (info: WorkerInfo) => W;
/**
* 默认的 getWorker
* @param url
* @param name
* @returns
*/
export declare function getWorker_Default(info: WorkerInfo): Worker;
/**
* 定义命名的函数
*
*/
export declare interface INamedFunction {
/**
* 保存函数的变量名
*/
name?: Optional<string>;
/**
* 函数
*/
fun: AnyFunction;
}
/**
* 命名函数的数组
*/
export declare type INamedFunctionList = (AnyFunction | INamedFunction | INamedFunctionMap)[];
/**
* 定义命名的函数
*
* @remarks
* 属性名字作为保存函数的变量名,即:函数名
*/
export declare interface INamedFunctionMap {
[name: string | number]: AnyFunction;
}
/**
* 命名函数选项的综合定义
*/
export declare type INamedFunctions = INamedFunctionList | INamedFunctionMap;
/**
* CallOptions 的类型保卫
* @param target
* @returns
*/
export declare function isCallOptions(target: any): target is CallOptions;
/**
* worker 的代码选项
*/
export declare interface IWorkerCodes {
/**
* 代码块
* @remarks
* - `code` 和 `named` 中的所有具有名字的 函数和数据都会被挂载在 `Worker` 中的 `globalThis` 上,其中 名字会作为 属性名字;
*
* - `code` 和 `named`中的 匿名函数 以及 `iife` 中的函数 会被作为 立即调用函数在 `Worker` 启动时作为顶层代码被立即执行;
*/
code?: Optional<CodePartOptions>;
/**
* 命名的函数
*
* @remarks
* 这些函数会被保存在 `Worker` 中的对应名字的全局变量中。
*
* - `code` 和 `named` 中的所有具有名字的 函数和数据都会被挂载在 `Worker` 中的 `globalThis` 上,其中 名字会作为 属性名字;
*
* - `code` 和 `named`中的 匿名函数 以及 `iife` 中的函数 会被作为 立即调用函数在 `Worker` 启动时作为顶层代码被立即执行;
*/
named?: Optional<INamedFunctions>;
/**
* 在 Wokrer 中会被立即执行的函数
* @remarks
* 这些函数会被作为 立即调用函数在 Worker 启动时作为顶层代码被立即执行;
*/
iife?: Optional<AnyFunction[]>;
/**
* 会作为 message 事件监听器的函数。
* @remarks
* 这些函数会在 Worker 中接收 `message` 事件;
*
* **注意:** 并不是所有的 监听器 都会被直接添加到 `message` 事件上;只有以 函数名字(即:`JSIdentifier` 类型的监听器) 指定的 事件会被直接添加到 `message` 事件上,其它类型的监听器都是以函数调用并传递 `message` 事件参数的形式来响应 `message` 事件,
*/
message?: Optional<(AnyFunction | JSIdentifier | Partial<INamedFunction>)[]>;
}
/**
* js 的标识符
*
* @remarks
*
* 比如变量名
*/
declare type JSIdentifier = string;
export { listenMessages_Dep }
/**
* 将所有成员都 转为 异步h命令
*
* @remarks
* 所有的方法的入参不变,返回参数都变为解决值为对应类型的 Promise
* 所有的属性都变为返回解决值为对应类型的 Promise 的方法
*/
export declare type MembersToAsyncCMD<Target> = {
[N in keyof Target]: AsyncCMD<Target[N]>;
};
export declare type SortComparer<Item> = (a: Item, b: Item) => number;
/**
* 排序队列
* @remarks
* 优先队列的极简实现;即优化了排序的性能,又保持代码精简;
*/
export declare class SortQueue<Item = any> {
comparer: SortComparer<Item>;
constructor(comparer: SortComparer<Item>, items?: Item[]);
/**
* 队列
* @remarks
* 保存所有的元素
*/
get queue(): Item[];
set queue(value: Item[]);
protected _queue: Item[];
/**
* 第一个元素
*/
get first(): Item;
/**
* 最后一个元素
*/
get last(): NonNullable<Item>;
/**
* 添加元素
* @param items
* @returns 返回item最终的索引
*/
add(item: Item): number;
/**
* 添加元素
* @param items
*/
addItems(items: Iterable<Item>): void;
/**
* 删除元素
* @param items
* @returns 返回item删除前所在的索引
*/
delete(item: Item): number;
/**
* 删除元素
* @param items
*/
deleteItems(items: Iterable<Item>): void;
/**
* 对队列中的所有元素重新排序
*/
sort(): void;
/**
* 排序 item
* @param item
* @returns 如果item 不在队列中,返回 false;否则返回 true
*/
sortItem(item: Item): number;
/**
* 前向排序
* @param item
* @returns 返回item最终的索引
*/
forwardSort(item: Item): number;
/**
* 后向排序
* @param item
* @returns 返回item最终的索引
*/
backwardSort(item: Item): number;
/**
* 排序 item
* @param index
* @returns 返回item最终的索引
*/
sortItemForIndex(index: number): number;
/**
* 前向排序
* @param index
* @returns 返回item最终的索引
*/
forwardSortForIndex(index: number): number;
/**
* 后向排序
* @param index
* @returns 返回item最终的索引
*/
backwardSortForIndex(index: number): number;
}
/**
* 将所有方法都 转为 异步方法
*
* @remarks
* 所有的方法的入参不变,返回参数都变为解决值为对应类型的 Promise
*
* @typeParam Methods - 包含方法的对象
*/
export declare type ToAsyncMethods<Methods extends INamedFunctionMap> = {
[N in keyof Methods]: AsyncFun<Methods[N]>;
};
/**
* 动态Worker 抽像基类
*
* @remarks
* 动态 Worker 具备以下特点:
*
* - 往 Worker 中添加函数、全局变量 等
*
* - 调用 Worker 中的任意全局函数 或 全局变量
*
* - 像调用本地方法一样调用 Worker 里的方法
*
* - 会自动给实例自身添加快捷命令
*
* - 支持异步、流
*
* - 支持异步和流互相嵌套
*
* - 支持 Worker 和 SharedWorker
*/
export declare abstract class WorkerClient<W extends AbstractWorker = Worker> {
constructor(named?: Optional<INamedFunctions>);
/**
* 实例的计数
*
* @remarks
* 用于给每次调用生成 id
*/
protected static instanceCount: number;
readonly id: number;
/**
* Worker 的实例
*/
abstract worker: DWorker<W>;
/**
* 消息端口
*/
get port(): MessagePort;
/**
* 获取 Worker 和 对应的 消息端口
*/
get workerAndPort(): [DWorker<W>, MessagePort];
/**
* 获取消息端口
* @param worker
* @returns
*/
getPort(worker: W): MessagePort;
/**
* 正在执行中的任务数
*/
abstract executingCount: number;
/**
* 执行已开始
* @remarks
* 开始执行
*/
execStarted(worker: DWorker<W>, execRec: ExecRecord): void;
/**
* 执行已开始
* @remarks
* 开始执行
*/
execEnded(worker: DWorker<W>): void;
/**
* 执行命令的计数
*
* @remarks
* 用于给每次执行命令时生成 id
*/
protected execCount: number;
/**
* 获取本次执行的执行 id
* @param cmdName
* @returns
*/
getExecId(cmdName?: Optional<string>): string;
/**
* 根据调用信息生成调用记录数据
* @param exec - 调用信息
* @returns
*/
getExecRecord(exec: Exec): ExecRecord;
/**
* 监听响应
* @param id
* @returns
*/
listenResponse(id: string, worker: DWorker<W>): Promise<any>;
/**
* 执行 worker 中的命令
*
* @remarks
* 当 worker 中成功执行,且 this 上没有对应的成员时,则会自动新增对应的成员方法
*
* @param exec - 命令信息
* @param transfer - 传递给 Worker 的可传递对象。这些对象的所有权将被转移给 Worker,而发当前环境将不再保有所有权。
* @returns
*/
execCMD(exec: Exec, transfer?: Transferable[]): Promise<any>;
/**
* 往自身上添加命令成员
* @remarks
* 会给实例自身上添加一个执行命令的快捷命令
*
* @param name
* @param isProperty - 添加到实例自身的快捷命令是否作为属性;如果是 true,则会在实例自身上生成快捷属性
*/
setCMDToSelf(name: string, isProperty?: Optional<boolean>): boolean;
}
/**
* worker 的信息
*/
export declare interface WorkerInfo {
/**
* worker 要加载的代码的url
*/
url: string;
/**
* worker 的名字
*/
name: string;
/**
* worker 客户端 的 id
*/
clientId: number;
/**
* worker 的 id
*/
id: number;
}
/**
* worker 优先级比较器
* @remarks
* 按照 executingCount 的从小到大排列
* @param a
* @param b
*/
export declare function workerPriorityComparator<W extends AbstractWorker>(a: DWorker<W>, b: DWorker<W>): number;
export { }