chore: account

This commit is contained in:
xiaojunnuo
2024-09-22 02:06:34 +08:00
parent 0451fa7573
commit bdc0227c08
9 changed files with 163 additions and 73 deletions

View File

@@ -1,51 +1,90 @@
import { nanoid } from 'nanoid';
export type IframeMessageData = {
export type IframeMessageData<T> = {
action: string;
id: string;
data: any;
data?: T;
replyId?: string;
errorCode?: number; //0为成功
message?: string;
};
export type IframeMessageReq = {
req: IframeMessageData;
onReply: (data: IframeMessageData) => void;
export type IframeMessageReq<T = any, R = any> = {
req: IframeMessageData<T>;
onReply: (data: IframeMessageData<R>) => void;
};
export class IframeException extends Error {
code?: number = 0;
constructor(data: IframeMessageData<any>) {
super(data.message);
this.code = data.errorCode;
}
}
export class IframeClient {
messageBucket: Record<string, IframeMessageReq> = {};
requestQueue: Record<string, IframeMessageReq> = {};
//当前客户端是否是父级页面
iframe?: HTMLIFrameElement;
handlers: Record<string, (data: IframeMessageData<any>) => Promise<void>> = {};
constructor(iframe?: HTMLIFrameElement) {
this.iframe = iframe;
window.addEventListener('message', (event: MessageEvent<IframeMessageData>) => {
window.addEventListener('message', async (event: MessageEvent<IframeMessageData<any>>) => {
const data = event.data;
if (data.replyId) {
const req = this.messageBucket[data.replyId];
if (req) {
req.onReply(data);
delete this.messageBucket[data.replyId];
if (data.action) {
console.log('收到消息', data);
try {
const handler = this.handlers[data.action];
if (handler) {
const res = await handler(data);
if (data.id && data.action !== 'reply') {
await this.send('reply', res, data.id);
}
} else {
throw new Error(`action:${data.action} 未注册处理器`);
}
} catch (e: any) {
await this.send('reply', {}, data.id, 500, e.message);
}
}
});
this.register('reply', async data => {
const req = this.requestQueue[data.replyId!];
if (req) {
req.onReply(data);
delete this.requestQueue[data.replyId!];
}
});
}
isInFrame() {
return window.self !== window.top;
}
async send(action: string, data?: any, replyId?: string) {
const reqMessageData: IframeMessageData = {
register<T = any>(action: string, handler: (data: IframeMessageData<T>) => Promise<void>) {
this.handlers[action] = handler;
}
async send<R = any, T = any>(action: string, data?: T, replyId?: string, errorCode?: number, message?: string): Promise<IframeMessageData<R>> {
const reqMessageData: IframeMessageData<T> = {
id: nanoid(),
action,
data,
replyId,
errorCode,
message,
};
return new Promise((resolve, reject) => {
const onReply = async (reply: IframeMessageData) => {
const onReply = async (reply: IframeMessageData<R>) => {
if (reply.errorCode && reply.errorCode > 0) {
reject(new IframeException(reply));
return;
}
resolve(reply);
};
this.messageBucket[reqMessageData.id] = {
this.requestQueue[reqMessageData.id] = {
req: reqMessageData,
onReply,
};