From 93d41169e141a34f9765218b9ec49f4dc4114a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E4=B8=80=E4=B9=8B?= Date: Tue, 12 Nov 2024 18:04:28 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 +- packages/message/extension.ts | 22 +++--- packages/message/index.ts | 122 +++++++++++++++++++++------------- pnpm-lock.yaml | 3 + src/service_worker.ts | 7 +- 5 files changed, 99 insertions(+), 58 deletions(-) diff --git a/package.json b/package.json index 7311a4b..ae101ab 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "i18next": "^23.16.4", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-i18next": "^15.1.0" + "react-i18next": "^15.1.0", + "uuid": "^11.0.3" }, "devDependencies": { "@eslint/compat": "^1.2.0", diff --git a/packages/message/extension.ts b/packages/message/extension.ts index e32c088..705c42b 100644 --- a/packages/message/extension.ts +++ b/packages/message/extension.ts @@ -1,18 +1,18 @@ -import EventEmitter from 'eventemitter3'; -import { Connect } from '.'; +import EventEmitter from "eventemitter3"; +import { IConnect, IServer } from "."; -export class ExtServer { +export class ExtServer implements IServer { private EE: EventEmitter; constructor() { this.EE = new EventEmitter(); chrome.runtime.onConnect.addListener((port) => { - this.EE.emit('connect', new ExtConnect(port)); + this.EE.emit("connect", port.name, new ExtConnect(port)); }); } - onConnect(callback: (con: Connect) => void) { - this.EE.on('connect', callback); + onConnect(callback: (eventName: string, con: IConnect) => void) { + this.EE.on("connect", callback); } } @@ -20,7 +20,7 @@ export function connect() { return new ExtConnect(chrome.runtime.connect()); } -export class ExtConnect implements Connect { +export class ExtConnect implements IConnect { private EE: EventEmitter; private port: chrome.runtime.Port; @@ -28,10 +28,10 @@ export class ExtConnect implements Connect { this.EE = new EventEmitter(); this.port = port; port.onMessage.addListener((message) => { - this.EE.emit('message', message); + this.EE.emit("message", message); }); port.onDisconnect.addListener(() => { - this.EE.emit('disconnect'); + this.EE.emit("disconnect"); this.EE.removeAllListeners(); }); } @@ -41,11 +41,11 @@ export class ExtConnect implements Connect { } onMessage(callback: (message: unknown) => void) { - this.EE.on('message', callback); + this.EE.on("message", callback); } onDisconnect(callback: () => void) { - this.EE.on('disconnect', callback); + this.EE.on("disconnect", callback); } disconnect() { diff --git a/packages/message/index.ts b/packages/message/index.ts index 77c4d9e..25b2519 100644 --- a/packages/message/index.ts +++ b/packages/message/index.ts @@ -1,11 +1,11 @@ -import EventEmitter from 'eventemitter3'; -import { v4 as uuidv4 } from 'uuid'; +import EventEmitter from "eventemitter3"; +import { v4 as uuidv4 } from "uuid"; -export interface Server { - onConnect: (callback: (con: Connect) => void) => void; +export interface IServer { + onConnect: (callback: (eventName: string, con: IConnect) => void) => void; } -export interface Connect { +export interface IConnect { postMessage: (message: unknown) => void; onMessage: (callback: (message: unknown) => void) => void; onDisconnect: (callback: () => void) => void; @@ -13,51 +13,83 @@ export interface Connect { } // 消息通道, 通过连接封装消息通道 -export class MessageChannel { +export class Server { private EE: EventEmitter; - // 实例id - private id: string; - constructor(private connect: Connect) { + constructor(private connect: IServer) { this.EE = new EventEmitter(); - this.id = uuidv4(); - connect.onMessage((message) => { - // 判断消息是否为连接消息 - if (message && typeof message === 'object') { - const data = message as { type: string; id: string }; - // 判断实例 - if (data.id == this.id) { - switch (data.type) { - case 'connect': - // 建立连接 - break; - case 'message': - // 发送消息 - break; - } - } - } + this.connect.onConnect((eventName, con) => { + this.EE.emit(eventName, con); }); } - // 发送一次消息并接收结果 - async send(message: unknown) { - return new Promise((resolve) => { - const callback = (message: unknown) => { - this.connect.onMessage(callback); - resolve(message); - }; - this.connect.onMessage(callback); - this.connect.postMessage(message); - }); - } - - // 发送消息 - postMessage(message: unknown) { - this.connect.postMessage({ - type: 'message', - id: this.id, - data: message, - }); + on(eventName: string, callback: (con: IConnect) => void) { + this.EE.on(eventName, callback); + } +} + +export class Connect { + private EE: EventEmitter; + + constructor( + private id: string | IConnect, + private con: IConnect + ) { + this.EE = new EventEmitter(); + if (arguments.length === 1) { + this.con = id as IConnect; + this.con.onMessage((message) => { + const data = message as { eventName: string; data: unknown[]; messageId: string }; + data.data.push(this.callbackFunc(data.messageId)); + this.EE.emit(data.eventName, ...data.data); + }); + } else { + // 子连接 + this.con.onMessage((message) => { + const data = message as { eventName: string; data: unknown; id: string }; + if (data.eventName === "subcon") { + if (data.id !== this.id) return; + this.messageHandler(data.data); + } + }); + } + this.con.onDisconnect(() => { + this.EE.emit("disconnect"); + this.EE.removeAllListeners(); + }); + } + + private callbackFunc(msgId: string): (...data: unknown[]) => void { + return function (...data: unknown[]) { + this.con.postMessage({ eventName: "callback", data, messageId: msgId }); + }; + } + + private messageHandler(data: unknown) { + const subData = data.data as { eventName: string; data: unknown[]; messageId: string }; + subData.data.push(this.callbackFunc(subData.messageId)); + this.EE.emit(subData.eventName, ...subData.data); + } + + on(eventName: string, callback: (message: unknown) => void) { + this.EE.on(eventName, callback); + } + + send(eventName: string, ...data: unknown[]) { + this.con.postMessage({ eventName, data }); + } + + emit(eventName: string, ...data: unknown[]) { + // 判断最后一个参数是否为函数 + const callback = data.pop(); + if (typeof callback !== "function") { + data.push(callback); + } + this.con.postMessage({ eventName, data, messageId: uuidv4() }); + } + + // 子连接 + connect() { + return new Connect(uuidv4(), this.con); } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9b3efc1..6f51e5e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ importers: react-i18next: specifier: ^15.1.0 version: 15.1.0(i18next@23.16.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + uuid: + specifier: ^11.0.3 + version: 11.0.3 devDependencies: '@eslint/compat': specifier: ^1.2.0 diff --git a/src/service_worker.ts b/src/service_worker.ts index b491783..ee6e03d 100644 --- a/src/service_worker.ts +++ b/src/service_worker.ts @@ -1,4 +1,5 @@ import { ExtServer } from "@Packages/message/extension"; +import { Server } from "@Packages/message"; async function setupOffscreenDocument() { // 创建运行后台脚本的沙盒环境 @@ -20,7 +21,11 @@ async function main() { // 初始化沙盒环境 await setupOffscreenDocument(); // 监听消息 - new ExtServer(); + const extServer = new ExtServer(); + const server = new Server(extServer); + server.on("", (con) => { + + }); } main();