forked from fanruan/fineui
Browse Source
Merge in VISUAL/fineui from ~TELLER/fineui:KERNEL-11169 to master * commit 'b78e9a4795996127f55440e115919e96b83a05e7': feat: 添加demo chore: eslint修复 refactor: 调整下数据结构 fix: worker环境秀谷 feat: 输出workers refactor: 修改下export feat: 主次线程入口abstract类 feat: action基础类 feat: 新增各线程controller refactor: 改名更换位置 refactor: 移动个位置 refactor: 改名 chore: 更新版本号 refactor: 统一下名字 refactor: 改个名字 feat: 框架三大件写完 chore: 更新依赖 feat: 新增promise判断方法es6
Teller
2 years ago
19 changed files with 830 additions and 4 deletions
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
<title>Document</title> |
||||
<link rel="stylesheet" type="text/css" href="http://fanruan.design/fineui/2.0/fineui.min.css" /> |
||||
<script src="http://fanruan.design/fineui/2.0/fineui.min.js"></script> |
||||
</head> |
||||
<body> |
||||
<div id="wrapper"></div> |
||||
<script src="./worker_new/index.js"></script> |
||||
</body> |
||||
</html> |
@ -0,0 +1,105 @@
|
||||
document.cookie = "test=demo"; |
||||
|
||||
// worker获取主线程资源
|
||||
var CookieAction = BI.inherit(BI.Workers.WorkerBaseAction, { |
||||
addActionHandler: function() { |
||||
this.controller.addActionHandler("Cookie", this.getCookie.bind(this)); |
||||
}, |
||||
|
||||
getCookie: function() { |
||||
return document.cookie; |
||||
} |
||||
}); |
||||
|
||||
// 调用worker计算
|
||||
var FibonacciAction = BI.inherit(BI.Workers.WorkerBaseAction, { |
||||
addActionHandler: function() {}, |
||||
|
||||
getResult: function(times) { |
||||
return this.controller.requestPromise("Fibonacci", { times: times }) |
||||
.then(function(v) { |
||||
console.log(v); |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
// 主线程与worker多次交互
|
||||
const HeartBeatCheckAction = BI.inherit(BI.Workers.WorkerBaseAction, { |
||||
addActionHandler: function() { |
||||
this.controller.addActionHandler("HeartBeatChecked", this.recieveHeartBeatChecked.bind(this)); |
||||
}, |
||||
|
||||
recieveHeartBeatChecked: function (payload) { |
||||
console.log("heartbeat: " + payload.time); |
||||
}, |
||||
|
||||
startHeatBeatCheck: function() { |
||||
return this.controller.request("HeartBeatCheckStart"); |
||||
}, |
||||
|
||||
stopHeatBeatCheck: function() { |
||||
return this.controller.request("HeartBeatCheckStop"); |
||||
} |
||||
}); |
||||
|
||||
var WorkerThreadWorker = BI.inherit(BI.Workers.MainThreadWorker, { |
||||
initActions: function() { |
||||
this.cookieAction = this.createAction(CookieAction); |
||||
|
||||
this.fibonacciAction = this.createAction(FibonacciAction); |
||||
|
||||
this.heartBeatCheckAction = this.createAction(HeartBeatCheckAction); |
||||
}, |
||||
|
||||
calculateFibonacci: function(times) { |
||||
this.fibonacciAction.getResult(times); |
||||
}, |
||||
|
||||
startHeatBeatCheck: function() { |
||||
this.heartBeatCheckAction.startHeatBeatCheck(); |
||||
}, |
||||
|
||||
stopHeatBeatCheck: function() { |
||||
this.heartBeatCheckAction.stopHeatBeatCheck(); |
||||
} |
||||
}); |
||||
|
||||
var mainThreadWorker = new WorkerThreadWorker({ |
||||
workerUrl: "./worker_new/worker.js", |
||||
workerName: "demo" |
||||
}); |
||||
|
||||
BI.createWidget({ |
||||
type: "bi.vertical", |
||||
element: "#wrapper", |
||||
vgap: 10, |
||||
hgap: 10, |
||||
items: [ |
||||
{ |
||||
type: "bi.button", |
||||
text: "点击计算斐波那契数列第40项", |
||||
width: 200, |
||||
handler: function() { |
||||
console.log("click"); |
||||
|
||||
mainThreadWorker.calculateFibonacci(40); |
||||
} |
||||
}, |
||||
{ |
||||
type: "bi.button", |
||||
text: "开始心跳", |
||||
width: 200, |
||||
handler: function() { |
||||
mainThreadWorker.startHeatBeatCheck(); |
||||
} |
||||
}, |
||||
{ |
||||
type: "bi.button", |
||||
text: "停止心跳", |
||||
width: 200, |
||||
handler: function() { |
||||
mainThreadWorker.stopHeatBeatCheck(); |
||||
} |
||||
} |
||||
] |
||||
}); |
@ -0,0 +1,80 @@
|
||||
self.importScripts("https://fanruan.design/fineui/fineui_without_jquery_polyfill.js"); |
||||
|
||||
var CookieAction = BI.inherit(BI.Workers.WorkerBaseAction, { |
||||
addActionHandler: function() {}, |
||||
|
||||
getCookie: function() { |
||||
return this.controller.requestPromise("Cookie"); |
||||
} |
||||
}); |
||||
|
||||
function fibonacci(n) { |
||||
if (n === 1 || n === 2) { |
||||
return 1; |
||||
} |
||||
|
||||
return fibonacci(n - 2) + fibonacci(n - 1); |
||||
} |
||||
|
||||
var FibonacciAction = BI.inherit(BI.Workers.WorkerBaseAction, { |
||||
addActionHandler: function() { |
||||
this.controller.addActionHandler("Fibonacci", this.getResult.bind(this)); |
||||
}, |
||||
|
||||
getResult: function(payload) { |
||||
return fibonacci(payload.times); |
||||
} |
||||
}); |
||||
|
||||
const HeartBeatCheckAction = BI.inherit(BI.Workers.WorkerBaseAction, { |
||||
addActionHandler: function() { |
||||
this.controller.addActionHandler("HeartBeatCheckStart", this.startHeatBeatCheck.bind(this)); |
||||
this.controller.addActionHandler("HeartBeatCheckStop", this.stopHeatBeatCheck.bind(this)); |
||||
}, |
||||
|
||||
startHeatBeatCheck: function() { |
||||
var self = this; |
||||
|
||||
if (!this.timer) { |
||||
console.log("heart beat check started"); |
||||
|
||||
this.timer = setInterval(function() { |
||||
// 模拟请求
|
||||
setTimeout(function() { |
||||
self.controller.request("HeartBeatChecked", { |
||||
time: new Date() |
||||
}); |
||||
}, 50); |
||||
}, 5 * 1000); |
||||
} else { |
||||
console.log("heart beat has already started!"); |
||||
} |
||||
}, |
||||
|
||||
stopHeatBeatCheck: function() { |
||||
console.log("heart beat check stopped"); |
||||
|
||||
clearInterval(this.timer); |
||||
} |
||||
}); |
||||
|
||||
var WorkerThreadWorker = BI.inherit(BI.Workers.WorkerThreadWorker, { |
||||
initActions: function() { |
||||
this.cookieAction = this.createAction(CookieAction); |
||||
|
||||
this.fibonacciAction = this.createAction(FibonacciAction); |
||||
|
||||
this.heartBeatCheckAction = this.createAction(HeartBeatCheckAction); |
||||
}, |
||||
|
||||
fetchCookie: function() { |
||||
return this.cookieAction.getCookie() |
||||
.then(function (v) { |
||||
console.log(v); |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
var workerThreadWorker = new WorkerThreadWorker(); |
||||
|
||||
workerThreadWorker.fetchCookie(); |
@ -0,0 +1,28 @@
|
||||
import type { WorkerBaseController } from "../controller/worker.controller"; |
||||
|
||||
/** |
||||
* 事务的基类 |
||||
*/ |
||||
export class WorkerBaseAction { |
||||
/** |
||||
* 通信控制器 |
||||
*/ |
||||
protected controller: WorkerBaseController; |
||||
|
||||
/** |
||||
* 线程上的 action 集合, 用于调用其他命名空间下的事务 |
||||
*/ |
||||
protected threadAction: any; |
||||
|
||||
public constructor(controller: WorkerBaseController, threadAction: any) { |
||||
this.controller = controller; |
||||
this.threadAction = threadAction; |
||||
|
||||
this.addActionHandler(); |
||||
} |
||||
|
||||
/** |
||||
* 添加事务的处理器 |
||||
*/ |
||||
protected addActionHandler() {} |
||||
} |
@ -0,0 +1,131 @@
|
||||
import type { IWorkerController, IWorkerMessage } from '../worker.core'; |
||||
import { WorkerChannel } from '../worker.channel'; |
||||
|
||||
/** |
||||
* 通信控制器 |
||||
* |
||||
* @class WorkerBaseController |
||||
*/ |
||||
export class WorkerBaseController implements IWorkerController { |
||||
/** |
||||
* 原生 worker, 在子类中实例化 |
||||
*/ |
||||
protected worker: Worker; |
||||
|
||||
/** |
||||
* 通信 Channel, 在子类中实例化 |
||||
*/ |
||||
protected channel: WorkerChannel; |
||||
|
||||
/** |
||||
* 事务处理器 Map |
||||
*/ |
||||
protected actionHandlerMap: { |
||||
[propsName: string]: (payload: any) => any; |
||||
}; |
||||
|
||||
public constructor() { |
||||
this.actionHandlerMap = {}; |
||||
} |
||||
|
||||
/** |
||||
* 发送事务,不等待结果 |
||||
* |
||||
* @param actionType 事务类型 |
||||
* @param payload 负载 |
||||
*/ |
||||
public request(actionType: string, payload: any): void { |
||||
if (this.channel) { |
||||
return this.channel.request(actionType, payload); |
||||
} |
||||
|
||||
console.error('No channel.'); |
||||
|
||||
return; |
||||
} |
||||
|
||||
/** |
||||
* 发送 Promise 形式的事务, 在 then 中获取响应 |
||||
* |
||||
* @param actionType 事务类型 |
||||
* @param payload 负载 |
||||
* @param [timeout] 响应的超时; Worker 通道是可靠的, 超时后只上报, 不阻止当前请求 |
||||
*/ |
||||
public requestPromise<T = any>(actionType: string, payload: any = '', timeout?: number): Promise<T> { |
||||
// 有 Channel 实例才能进行通信, 此时还没有实例化是浏览器不支持创建 worker
|
||||
if (this.channel) { |
||||
return this.channel.requestPromise<T>(actionType, payload, timeout); |
||||
} |
||||
|
||||
// 兼容上层调用的 .then().catch()
|
||||
return Promise.reject(new Error('No channel.')); |
||||
} |
||||
|
||||
/** |
||||
* 添加事务处理器, 不允许重复添加 |
||||
* |
||||
* @param actionType 事务类型 |
||||
* @param handler 事务处理器 |
||||
*/ |
||||
public addActionHandler(actionType: string, handler: (payload: any) => any): void { |
||||
if (this.hasActionHandler(actionType)) { |
||||
throw new Error(`Add action \`${actionType}\` handler repeat`); |
||||
} |
||||
this.actionHandlerMap[actionType] = handler; |
||||
} |
||||
|
||||
/** |
||||
* 事务处理器, 提供给通信 Channel 调用 |
||||
* |
||||
* @param message 会话消息 |
||||
* @returns |
||||
*/ |
||||
public actionHandler(message: IWorkerMessage): Promise<any> { |
||||
const { actionType, payload } = message; |
||||
|
||||
if (this.hasActionHandler(actionType)) { |
||||
// 执行指定的事务处理器, 并返回 Promise 封装的事务结果
|
||||
try { |
||||
const actionResult = this.actionHandlerMap[actionType](payload); |
||||
|
||||
// 对于 Promise 形式的结果, 需要进行 Promise 错误捕获
|
||||
if (BI.isPromise(actionResult)) { |
||||
return actionResult.catch(error => Promise.reject(error)); |
||||
} |
||||
|
||||
// 对数据结果, 包装为 Promise
|
||||
return Promise.resolve(actionResult); |
||||
} catch (error) { |
||||
// 继续抛出给外层
|
||||
return Promise.reject(error); |
||||
} |
||||
} else { |
||||
throw new Error(`Not Found Session Handler \`${actionType}\`.`); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 添加 worker onmessage 事件的回调 |
||||
* |
||||
* @param {(event: any) => void} onmessage 回调函数 |
||||
* @returns {() => void} 移除监听函数 |
||||
*/ |
||||
public addOnmessageListener(onmessage: (event: any) => void): () => void { |
||||
this.worker.addEventListener('message', onmessage); |
||||
|
||||
// 返回移除监听函数
|
||||
return () => { |
||||
this.worker.removeEventListener('message', onmessage); |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* 判断是否有指定事务的处理器 |
||||
* |
||||
* @param actionType 事务类型 |
||||
* @returns {boolean} |
||||
*/ |
||||
protected hasActionHandler(actionType: string): boolean { |
||||
return !!this.actionHandlerMap[actionType]; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -0,0 +1,200 @@
|
||||
import { IWorkerController, WorkerMessageType, IWorkerMessage } from './worker.core'; |
||||
|
||||
const COMMUNICATION_TIMEOUT = 30000; |
||||
|
||||
/** |
||||
* 通信通道 |
||||
*/ |
||||
export class WorkerChannel { |
||||
/** |
||||
* Web Worker 实例 |
||||
*/ |
||||
private worker: Worker; |
||||
|
||||
/** |
||||
* 上层通信控制器 |
||||
*/ |
||||
private controller: IWorkerController; |
||||
|
||||
/** |
||||
* 会话响应器 Map |
||||
*/ |
||||
private sessionHandlerMap: { |
||||
[propsName: string]: Function; |
||||
}; |
||||
|
||||
public constructor(worker: Worker, controller: IWorkerController) { |
||||
this.worker = worker; |
||||
this.controller = controller; |
||||
|
||||
this.sessionHandlerMap = {}; |
||||
|
||||
// 绑定 worker onmessage 事件的回调
|
||||
this.worker.addEventListener('message', this.onmessage.bind(this)); |
||||
} |
||||
|
||||
/** |
||||
* 发送响应 |
||||
* |
||||
* @param sessionId 会话 Id |
||||
* @param payload 负载 |
||||
*/ |
||||
public response(sessionId: string, actionType: string, payload: any): void { |
||||
this.postMessage({ |
||||
messageType: WorkerMessageType.REPLY, |
||||
actionType, |
||||
payload, |
||||
sessionId, |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* 发送请求, 不等待响应 |
||||
* |
||||
* @param actionType 事务类型 |
||||
* @param payload 负载 |
||||
*/ |
||||
public request(actionType: string, payload: any): void { |
||||
const sessionId = this.generateSessionId(); |
||||
this.postMessage({ |
||||
messageType: WorkerMessageType.REQUEST, |
||||
actionType, |
||||
payload, |
||||
sessionId, |
||||
}); |
||||
|
||||
// 不等待结果, 还会收到响应, 添加个空的会话响应器
|
||||
this.addSessionHandler(sessionId, () => {}); |
||||
} |
||||
|
||||
/** |
||||
* 发送请求, 并等待响应 |
||||
* |
||||
* @param actionType 事务类型 |
||||
* @param payload 负载 |
||||
* @param timeout 响应超时 |
||||
* @returns {Promise<IWorkerMessage>} 等待响应的 Promise |
||||
*/ |
||||
public requestPromise<T>(actionType: string, payload: any, timeout = COMMUNICATION_TIMEOUT): Promise<T> { |
||||
const sessionId = this.generateSessionId(); |
||||
const message = { |
||||
messageType: WorkerMessageType.REQUEST, |
||||
actionType, |
||||
payload, |
||||
sessionId, |
||||
}; |
||||
|
||||
// 请求封装为一个 Promise, 等待会话响应器进行 resolve
|
||||
const PromiseFunction = (resolve: Function, reject: Function): any => { |
||||
// 启动请求超时计时器
|
||||
const timeoutHandler = setTimeout(() => { |
||||
clearTimeout(timeoutHandler); |
||||
|
||||
reject(); |
||||
}, timeout); |
||||
|
||||
const sessionHandler: Function = (message: IWorkerMessage) => { |
||||
// 会话回调函数, 开始处理响应
|
||||
this.deleteSessionHandler(message.sessionId); |
||||
clearTimeout(timeoutHandler); |
||||
|
||||
resolve(message.payload); |
||||
}; |
||||
|
||||
this.addSessionHandler(sessionId, sessionHandler); |
||||
|
||||
// 开始发送请求
|
||||
this.postMessage(message); |
||||
}; |
||||
|
||||
return new Promise(PromiseFunction); |
||||
} |
||||
|
||||
/** |
||||
* 收到会话消息的处理函数 |
||||
* |
||||
* 发现是请求, 调用通信控制器的事务处理器进行处理, 获取事务结果并响应; |
||||
* 发现是响应,调用会话响应器 |
||||
* @param event worker 通信事件 |
||||
*/ |
||||
private onmessage(event: { data: IWorkerMessage }): void { |
||||
const { data: message } = event; |
||||
const { messageType, sessionId, actionType } = message; |
||||
|
||||
// 接收到请求
|
||||
if (messageType === WorkerMessageType.REQUEST) { |
||||
// 处理请求
|
||||
this.controller.actionHandler(message) |
||||
.then(actionResult => { |
||||
// 响应请求
|
||||
this.response(sessionId, actionType, actionResult); |
||||
}); |
||||
} |
||||
|
||||
// 接收到响应
|
||||
if (messageType === WorkerMessageType.REPLY) { |
||||
// 处理响应
|
||||
if (this.hasSessionHandler(sessionId)) { |
||||
this.sessionHandlerMap[sessionId](message); |
||||
} else { |
||||
throw new Error(`Session \`${sessionId}\` handler no exist`); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 封装的 worker 原生 postMessage 接口 |
||||
* 支持 structured clone 和 transfer 2种通信模式 |
||||
* |
||||
* @param message 会话消息 |
||||
*/ |
||||
private postMessage(message: IWorkerMessage): void { |
||||
this.worker.postMessage(message); |
||||
} |
||||
|
||||
/** |
||||
* 添加会话响应器 |
||||
* |
||||
* @param sessionId 会话 Id |
||||
* @param handler 会话响应器 |
||||
*/ |
||||
private addSessionHandler(sessionId: string, handler: Function): void { |
||||
if (!this.hasSessionHandler(sessionId)) { |
||||
this.sessionHandlerMap[sessionId] = handler; |
||||
} else { |
||||
throw new Error(`SessionId \`${sessionId}\` already exist!`); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 移除会话响应器 |
||||
* |
||||
* @param sessionId |
||||
*/ |
||||
private deleteSessionHandler(sessionId: string): void { |
||||
if (this.hasSessionHandler(sessionId)) { |
||||
delete this.sessionHandlerMap[sessionId]; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 生成每次独立会话的 Id |
||||
* |
||||
* @returns 会话 Id |
||||
*/ |
||||
private generateSessionId(): string { |
||||
const sessionId = `w_${BI.UUID()}`; |
||||
|
||||
return sessionId; |
||||
} |
||||
|
||||
/** |
||||
* 判断是否有指定会话的处理器 |
||||
* |
||||
* @param sessionId 会话 Id |
||||
* @returns {boolean} 判断结果 |
||||
*/ |
||||
private hasSessionHandler(sessionId: string): boolean { |
||||
return !!this.sessionHandlerMap[sessionId]; |
||||
} |
||||
} |
@ -0,0 +1,48 @@
|
||||
/** |
||||
* 会话消息类型枚举 |
||||
*/ |
||||
export const WorkerMessageType = { |
||||
REQUEST: 'REQUEST', |
||||
REPLY: 'REPLY', |
||||
}; |
||||
|
||||
/** |
||||
* 会话消息 |
||||
*/ |
||||
export interface IWorkerMessage { |
||||
messageType: string; |
||||
actionType: string; |
||||
sessionId: string; |
||||
|
||||
/** |
||||
* 数据交换参数 |
||||
*/ |
||||
payload: any; |
||||
} |
||||
|
||||
/** |
||||
* 通信控制器需要实现的 interface |
||||
*/ |
||||
export interface IWorkerController { |
||||
|
||||
/** |
||||
* 事务处理器 |
||||
*/ |
||||
actionHandler: (message: IWorkerMessage) => Promise<any>; |
||||
} |
||||
|
||||
/** |
||||
* Worker创建配置 |
||||
*/ |
||||
export interface IWorkerOptions { |
||||
|
||||
/** |
||||
* worker 资源 url |
||||
*/ |
||||
workerUrl: string; |
||||
|
||||
/** |
||||
* worker 实例名称 |
||||
*/ |
||||
workerName: string; |
||||
} |
@ -0,0 +1,49 @@
|
||||
import type { WorkerBaseAction } from "./action/worker.action"; |
||||
import { WorkerMainThreadController } from "./controller/worker.main_thread.controller"; |
||||
import { IWorkerOptions } from "./worker.core"; |
||||
|
||||
/** |
||||
* 主线程Worker |
||||
*/ |
||||
export abstract class MainThreadWorker { |
||||
/** |
||||
* Worker 名称 |
||||
*/ |
||||
public name: string; |
||||
|
||||
/** |
||||
* 主线程通信控制器 |
||||
*/ |
||||
public controller: WorkerMainThreadController; |
||||
|
||||
/** |
||||
* 是否已经终止掉 Worker |
||||
*/ |
||||
protected isTerminated = false; |
||||
|
||||
public constructor(options: IWorkerOptions) { |
||||
this.name = options.workerName; |
||||
this.controller = new WorkerMainThreadController(options); |
||||
this.initActions(); |
||||
} |
||||
|
||||
protected abstract initActions(): void; |
||||
|
||||
/** |
||||
* 销毁 worker 实例 |
||||
* 子实例需要销毁action |
||||
*/ |
||||
public terminate(): void { |
||||
this.controller.terminate(); |
||||
// 设置终止标志位
|
||||
this.isTerminated = true; |
||||
} |
||||
|
||||
/** |
||||
* 实例化action |
||||
* @param Action action类 |
||||
*/ |
||||
protected createAction<T extends typeof WorkerBaseAction>(Action: T): InstanceType<T> { |
||||
return (new Action(this.controller, this)) as InstanceType<T>; |
||||
} |
||||
} |
@ -0,0 +1,28 @@
|
||||
import type { WorkerBaseAction } from "./action/worker.action"; |
||||
import { WorkerThreadController } from "./controller/worker.worker_thread.controller"; |
||||
|
||||
/** |
||||
* worker线程实例 |
||||
*/ |
||||
export abstract class WorkerThreadWorker { |
||||
/** |
||||
* Worker 线程通信控制器 |
||||
*/ |
||||
protected controller: WorkerThreadController; |
||||
|
||||
public constructor() { |
||||
this.controller = new WorkerThreadController(); |
||||
|
||||
this.initActions(); |
||||
} |
||||
|
||||
protected abstract initActions(): void; |
||||
|
||||
/** |
||||
* 实例化action |
||||
* @param Action action类 |
||||
*/ |
||||
protected createAction<T extends typeof WorkerBaseAction>(Action: T): InstanceType<T> { |
||||
return (new Action(this.controller, this)) as InstanceType<T>; |
||||
} |
||||
} |
@ -0,0 +1,19 @@
|
||||
import { WorkerChannel } from "./worker.channel"; |
||||
import { WorkerBaseController } from "./controller/worker.controller"; |
||||
import { WorkerMessageType } from "./worker.core"; |
||||
import { WorkerMainThreadController } from "./controller/worker.main_thread.controller"; |
||||
import { WorkerThreadController } from "./controller/worker.worker_thread.controller"; |
||||
import { WorkerBaseAction } from "./action/worker.action"; |
||||
import { MainThreadWorker } from "./worker.main_thread"; |
||||
import { WorkerThreadWorker } from "./worker.worker_thread"; |
||||
|
||||
export const Workers = { |
||||
WorkerChannel, |
||||
WorkerBaseController, |
||||
WorkerMainThreadController, |
||||
WorkerThreadController, |
||||
WorkerBaseAction, |
||||
MainThreadWorker, |
||||
WorkerThreadWorker, |
||||
WorkerMessageType, |
||||
}; |
Loading…
Reference in new issue