diff --git a/types/globals.d.ts b/types/globals.d.ts index f35336db4..0b5805aa0 100644 --- a/types/globals.d.ts +++ b/types/globals.d.ts @@ -11,3 +11,5 @@ declare const Fix: Obj; declare interface String { replaceAll(regx: string, callback: (str: string) => void): string; } + +declare const _global: typeof window; diff --git a/typescript/core/worker/controller/worker.main_thread.controller.ts b/typescript/core/worker/controller/worker.main_thread.controller.ts new file mode 100644 index 000000000..6cabc8380 --- /dev/null +++ b/typescript/core/worker/controller/worker.main_thread.controller.ts @@ -0,0 +1,85 @@ +import { WorkerChannel } from "../worker.channel"; +import type { IWorkerOptions } from "../worker.core"; +import WorkerBaseController from "./worker.controller"; + +export class WorkerMainThreadController extends WorkerBaseController { + /** + * 浏览器是否实现了 HTML 规范的 Worker Class + */ + public static hasWorkerClass = !!_global.Worker; + + /** + * 是否支持 new Worker, 默认为 Wroker Class 是否实现 + */ + + public canNewWorker: boolean = WorkerMainThreadController.hasWorkerClass; + + /** + * 主线程 new Worker 起始时刻 + */ + public timeBeforeNewWorker: number; + + /** + * 主线程 new Worker 完毕时刻 + */ + public timeAfterNewWorker: number; + + public constructor(options: IWorkerOptions) { + super(); + + if (!this.canNewWorker) { + // 都没有 Worker Class, 没法继续了 + return; + } + + this.newWorker(options); + } + + /** + * 销毁 Worker 线程实例 + */ + public terminate(): void { + this.worker?.terminate(); + } + + protected reportActionHandlerError(actionType: string, error: any): void { + console.error(`Worker aciton ${actionType}:`, error); + + // 主线程的报错, 在 window.onerror 中可以拿到报错堆栈, 直接抛出即可 + throw new Error(error); + } + + /** + * 创建 Worker 线程实例 + */ + private newWorker(options: IWorkerOptions) { + this.timeBeforeNewWorker = Date.now(); + + try { + // 主线程通过 new Worker() 获取 Worker 实例 + this.worker = new Worker(options.workerUrl, { + name: options.workerName, + }); + + /** + * 监控和上报 worker 中的报错 + * window.onerror 中也能监控到 worker.onerror( Worker 运行报错) + */ + this.worker.onerror = (error): void => { + console.error('Worker onerror:', error); + }; + + this.timeAfterNewWorker = Date.now(); + + // 实例化 Channel + this.channel = new WorkerChannel(this.worker, { + actionHandler: this.actionHandler.bind(this), + }); + } catch (error) { + console.error('Init worker fail:', error); + + // 创建 worker 失败, 标识改为不支持 + this.canNewWorker = false; + } + } +} diff --git a/typescript/core/worker/controller/worker.worker_thread.controller.ts b/typescript/core/worker/controller/worker.worker_thread.controller.ts new file mode 100644 index 000000000..71abef337 --- /dev/null +++ b/typescript/core/worker/controller/worker.worker_thread.controller.ts @@ -0,0 +1,21 @@ +import { WorkerChannel } from "../worker.channel"; +import WorkerBaseController from "./worker.controller"; + +export class WorkerThreadController extends WorkerBaseController { + public constructor() { + super(); + + // Worker 线程中的全局环境 self 就是 Worker 实例 + this.worker = self as any; + this.channel = new WorkerChannel(this.worker, { + actionHandler: this.actionHandler.bind(this), + }); + } + + protected reportActionHandlerError(actionType: string, error: any): void { + console.error(`Worker aciton ${actionType}:`, error); + + // 正常抛出 + throw new Error(error); + } +}