diff --git a/src/messaging/Layer1Protocol.ts b/src/messaging/Layer1Protocol.ts index 03c8d55..769006a 100644 --- a/src/messaging/Layer1Protocol.ts +++ b/src/messaging/Layer1Protocol.ts @@ -16,69 +16,79 @@ type RespMsg = { msg?: string } +// 处理函数 +type Handler = (req: L1Req) => Promise + // 创建一个 Layer1Protocol 类,用于持久监听 port 并通过消息 ID 处理响应,支持超时 class Layer1Protocol { private port: chrome.runtime.Port private timeout: number - private requests: Map void, timer: number }> - private handler: (value: L1Req) => Promise + private requests: Map void, reject: (reason?: any) => void, timer: number }> + private handler: Handler - constructor(handler: (value: L1Req) => Promise, port: chrome.runtime.Port, timeout = 30000) { // 默认超时 30 秒 + constructor(handler: Handler, port: chrome.runtime.Port, timeout = 30000) { // 默认超时 30 秒 this.port = port; this.timeout = timeout; this.requests = new Map(); this.handler = handler - this._startListen() + // 开始监听 + this.port.onMessage.addListener(this._messageListener); } // 生成唯一 ID(简单示例,可以使用更复杂的生成策略) - _generateUniqueId() { + private _generateUniqueId() { return crypto.randomUUID() } - _startListen() { - // 持久监听 port.onMessage - this.port.onMessage.addListener((msg: ReqMsg) => { - const { id, type, req, res } = msg; - if (type === 'req') { - this.handler(req!).then(res => { - const response: RespMsg = { - code: 200, - msg: 'success', - data: res - } - this.port.postMessage({ id, type: 'res', res: response }); - }).catch(error => { - const response: RespMsg = { - code: 500, - msg: error.message, - } - this.port.postMessage({ id, type: 'res', res: response }); - }); - } else if (type === 'res') { - if (this.requests.has(id)) { - const { resolve, timer } = this.requests.get(id)!; - // 清除超时定时器 - clearTimeout(timer); - // 移除消息 ID - this.requests.delete(id); - // 通过 ID 找到对应的 Promise 并 resolve + private _messageListener = (msg: ReqMsg) => { + const { id, type, req, res } = msg; + if (type === 'req') { + this.handler(req!).then(res => { + const response: RespMsg = { + code: 200, + data: res + } + this.port.postMessage({ id, type: 'res', res: response }); + }).catch(error => {//业务错误 + const response: RespMsg = { + code: 500, + msg: error instanceof Error ? error.message : String(error), + } + this.port.postMessage({ id, type: 'res', res: response }); + }); + } else if (type === 'res') { + if (this.requests.has(id)) { + const { resolve, reject, timer } = this.requests.get(id)!; + // 清除超时定时器 + clearTimeout(timer); + // 移除消息 ID + this.requests.delete(id); + // 通过 ID 找到对应的 Promise 并 resolve + if (res!.code === 200) { resolve(res!.data!); - }else { - console.error('unknown response message id: ', id) + } else {//业务错误 + reject(new Error(`${res!.code}: ${res!.msg || 'Unknown error'}`)); } } else { - console.error('unknown message type: ', type) + console.error('unknown response message id: ', id) } - }); + } else {//语法格式错误 + console.error('unknown message type: ', type) + } + } + + dispose() { + this.port.onMessage.removeListener(this._messageListener); + this.requests.forEach(({ timer }) => clearTimeout(timer)); + this.requests.clear(); } // 使用 Promise 发送消息并等待响应,支持超时 sendMessage(req: L1Req): Promise { const id = this._generateUniqueId(); - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { // 设置一个超时定时器 const timer = setTimeout(() => { // 超时后执行 reject 并从 Map 中删除 @@ -87,7 +97,7 @@ class Layer1Protocol { }, this.timeout); // 将 resolve 和 timer 函数与消息 ID 绑定,存入 Map - this.requests.set(id, { resolve, timer }); + this.requests.set(id, { resolve, reject, timer }); // 发送消息,并附带 ID this.port.postMessage({ id, type: 'req', req });