alloy-worker
Version:
面向事务的高可用 Web Worker 通信框架
103 lines (85 loc) • 3.22 kB
text/typescript
import type { IAlloyWorkerOptions } from '../type';
import reportProxy from '../external/report-proxy';
import { WorkerMonitorId, WorkerErrorSource } from '../common/report-type';
import BaseController from '../common/base-controller';
import Channel from '../common/channel';
/**
* 主线程通信控制器
*/
export default class Controller extends BaseController {
/**
* 浏览器是否实现了 HTML 规范的 Worker Class
*/
public static hasWorkerClass = !!window.Worker;
/**
* 是否支持 new Worker, 默认为 Wroker Class 是否实现
*/
public canNewWorker: boolean = Controller.hasWorkerClass;
/**
* 主线程 new Worker 起始时刻
*/
public timeBeforeNewWorker: number;
/**
* 主线程 new Worker 完毕时刻
*/
public timeAfterNewWorker: number;
public constructor(options: IAlloyWorkerOptions) {
super();
this.isDebugMode = options.isDebugMode || false;
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);
// 事务处理器逻辑错误上报
reportProxy.monitor(WorkerMonitorId.ActionHandleError);
// 主线程的报错, 在 window.onerror 中可以拿到报错堆栈, 直接抛出即可
throw new Error(error);
}
/**
* 创建 Worker 线程实例
*/
private newWorker(options: IAlloyWorkerOptions) {
this.timeBeforeNewWorker = Date.now();
try {
// 主线程通过 new Worker() 获取 Worker 实例
this.worker = new Worker(options.workerUrl, {
name: options.workerName,
});
/**
* 监控和上报 worker 中的报错
* window.onerror 中也能监控到 worker.onerror( Worker 运行报错)
* 但是对于加载 js 资源 state 非 2xx, window.onerror 监控不到
*/
this.worker.onerror = (error): void => {
console.error('Worker onerror:', error);
// 主动上报错误和 monitor
reportProxy.raven(error);
reportProxy.monitor(WorkerErrorSource.WorkerOnerror);
reportProxy.monitor(WorkerMonitorId.WorkerOnerror);
};
this.timeAfterNewWorker = Date.now();
// 实例化 Channel
this.channel = new Channel(this.worker, {
actionHandler: this.actionHandler.bind(this),
isDebugMode: this.isDebugMode,
});
} catch (error) {
console.error('Init worker fail:', error);
// 创建 worker 失败, 标识改为不支持
this.canNewWorker = false;
// 主动上报错误和 monitor
reportProxy.raven(error);
reportProxy.monitor(WorkerErrorSource.CreateWorkerError);
}
}
}