diff --git a/packages/message/index.ts b/packages/message/index.ts index 32e2928..8c60673 100644 --- a/packages/message/index.ts +++ b/packages/message/index.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import EventEmitter from "eventemitter3"; import { v4 as uuidv4 } from "uuid"; @@ -23,6 +24,7 @@ export class Server { }); } + on(eventName: "connection", callback: (con: IConnect) => void): void; on(eventName: string, callback: (con: IConnect) => void) { this.EE.on(eventName, callback); } @@ -31,29 +33,11 @@ export class Server { export class Connect { private EE: EventEmitter; - private con: IConnect; - - constructor( - private id: string | IConnect, - con?: IConnect - ) { + constructor(private con: IConnect) { this.EE = new EventEmitter(); - if (arguments.length === 1) { - this.con = id as IConnect; - this.con.onMessage((message) => { - this.messageHandler(message); - }); - } else { - // 子连接 - this.con = con!; - 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.onMessage((message) => { + this.messageHandler(message); + }); this.con.onDisconnect(() => { this.EE.emit("disconnect"); this.EE.removeAllListeners(); @@ -67,12 +51,16 @@ export class Connect { } private messageHandler(data: unknown) { - const subData = data as { eventName: string; data: unknown[]; messageId: string }; + const subData = data as { eventName: string; data: unknown[]; messageId: string; conType: string; id: string }; + if (subData.eventName === "callback") { + this.EE.emit(subData.eventName + subData.messageId, ...subData.data); + return; + } subData.data.push(this.callbackFunc(subData.messageId)); this.EE.emit(subData.eventName, ...subData.data); } - on(eventName: string, callback: (message: unknown) => void) { + on(eventName: string, callback: (...args: any[]) => void) { this.EE.on(eventName, callback); } @@ -80,17 +68,18 @@ export class Connect { this.con.postMessage({ eventName, data }); } - emit(eventName: string, ...data: unknown[]) { + emit(eventName: string, ...data: any[]) { // 判断最后一个参数是否为函数 const callback = data.pop(); + const messageId = uuidv4(); if (typeof callback !== "function") { data.push(callback); + } else { + this.EE.on("callback" + messageId, (...args) => { + callback(...args); + }); } - this.con.postMessage({ eventName, data, messageId: uuidv4() }); - } - - // 子连接 - connect() { - return new Connect(uuidv4(), this.con); + const sendData = { eventName, data, messageId }; + this.con.postMessage(sendData); } } diff --git a/packages/message/message.test.ts b/packages/message/message.test.ts index 9c782ab..5cbbe99 100644 --- a/packages/message/message.test.ts +++ b/packages/message/message.test.ts @@ -1,42 +1,65 @@ // @vitest-environment jsdom -import { expect, test, vi } from "vitest"; +import { describe, expect, it, vi } from "vitest"; import { Server, Connect } from "."; import { connect, WindowServer } from "./window"; -test("server", async () => { - const myFunc = vi.fn(); - const server = new Server(new WindowServer(global.window)); - server.on("connection", (con) => { - myFunc(); - con.onMessage((message) => { - myFunc(message); +describe("server", () => { + it("hello", async () => { + const myFunc = vi.fn(); + const server = new Server(new WindowServer(global.window)); + server.on("connection", (con) => { + myFunc(); + con.onMessage((message) => { + myFunc(message); + }); }); + const client = connect(window, window); + client.postMessage("hello"); + await new Promise((resolve) => setTimeout(resolve, 10)); + expect(myFunc).toHaveBeenCalledTimes(2); + expect(myFunc).toHaveBeenCalledWith("hello"); }); - const client = connect(window, window); - client.postMessage("hello"); - await new Promise((resolve) => setTimeout(resolve, 1)); - expect(myFunc).toHaveBeenCalledTimes(2); - expect(myFunc).toHaveBeenCalledWith("hello"); }); -test("connect", async () => { - const myFunc = vi.fn(); - const server = new Server(new WindowServer(global.window)); - server.on("connection", (con) => { - myFunc(); - const wrapCon = new Connect(con); - wrapCon.on("hello", (message) => { - myFunc(message); - wrapCon.emit("world", "world"); +describe("connect", async () => { + it("hello", async () => { + const server = new Server(new WindowServer(global.window)); + const myFunc = vi.fn(); + server.on("connection", (con) => { + myFunc(); + const wrapCon = new Connect(con); + wrapCon.on("hello", (message) => { + myFunc(message); + wrapCon.emit("world", "world"); + }); }); + const client = new Connect(connect(window, window)); + client.on("world", (message) => { + myFunc(message); + }); + client.emit("hello", "hello"); + await new Promise((resolve) => setTimeout(resolve, 10)); + expect(myFunc).toHaveBeenCalledTimes(3); + expect(myFunc).toHaveBeenCalledWith("hello"); + expect(myFunc).toHaveBeenCalledWith("world"); }); - const client = new Connect(connect(window, window)); - client.on("world", (message) => { - myFunc(message); + it("response", async () => { + const server = new Server(new WindowServer(global.window)); + const myFunc = vi.fn(); + server.on("connection", (con) => { + const wrapCon = new Connect(con); + wrapCon.on("ping", (message, response) => { + myFunc(message); + response("pong"); + }); + }); + const client = new Connect(connect(window, window)); + client.emit("ping", "ping", (message: string) => { + myFunc(message); + }); + await new Promise((resolve) => setTimeout(resolve, 10)); + expect(myFunc).toHaveBeenCalledTimes(2); + expect(myFunc).toHaveBeenCalledWith("ping"); + expect(myFunc).toHaveBeenCalledWith("pong"); }); - client.emit("hello", "hello"); - await new Promise((resolve) => setTimeout(resolve, 1)); - expect(myFunc).toHaveBeenCalledTimes(3); - expect(myFunc).toHaveBeenCalledWith("hello"); - expect(myFunc).toHaveBeenCalledWith("world"); }); diff --git a/packages/message/window.ts b/packages/message/window.ts index 04cae19..3728be9 100644 --- a/packages/message/window.ts +++ b/packages/message/window.ts @@ -20,8 +20,9 @@ export class WindowServer implements IServer { } export function connect(source: Window, target: Window) { - const con = new WindowConnect(uuidv4(), source, target); - con.postMessage({ type: "connect" }); + const connectId = uuidv4(); + target.postMessage({ type: "connect", connectId }, "*"); + const con = new WindowConnect(connectId, source, target); return con; } @@ -35,14 +36,14 @@ export class WindowConnect implements IConnect { ) { this.EE = new EventEmitter(); this.source.addEventListener("message", (event) => { - if (event.data.id === id) { - this.EE.emit("message", event.data); + if (event.data.eventName === "message" && event.data.id === id) { + this.EE.emit("message", event.data.data); } }); } - postMessage(message: unknown) { - this.target.postMessage(message, "*"); + postMessage(data: unknown) { + this.target.postMessage({ eventName: "message", id: this.id, data }, "*"); } onMessage(callback: (message: unknown) => void) {