更新 @kevisual/api 版本至 0.0.16,增强 RouterViewItem 类型,添加 question、response 和 action 属性,重构 initRouterViewQuery 和 callWorker 方法以优化路由视图初始化和工作线程调用
This commit is contained in:
@@ -4,13 +4,26 @@ import { filter } from '@kevisual/js-filter'
|
||||
import { EventEmitter } from 'eventemitter3';
|
||||
|
||||
export const RouteTypeList = ['api', 'context', 'worker', 'page'] as const;
|
||||
export type RouterViewItem = RouterViewApi | RouterViewContext | RouterViewWorker | RouteViewPage;
|
||||
export type RouterViewItemInfo = RouterViewApi | RouterViewContext | RouterViewWorker | RouteViewPage;
|
||||
export type RouterViewItem<T = {}> = RouterViewItemInfo & T;
|
||||
|
||||
type RouteViewBase = {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
enabled?: boolean;
|
||||
/**
|
||||
* 提示问题
|
||||
*/
|
||||
question?: string;
|
||||
/**
|
||||
* 响应数据
|
||||
*/
|
||||
response?: any;
|
||||
/**
|
||||
* 默认动作配置
|
||||
*/
|
||||
action?: { path?: string; key?: string; id?: string; payload?: any;[key: string]: any };
|
||||
}
|
||||
export type RouterViewApi = {
|
||||
type: 'api',
|
||||
@@ -46,6 +59,30 @@ export type RouterViewWorker = {
|
||||
}
|
||||
} & RouteViewBase;
|
||||
|
||||
/**
|
||||
* 去掉不需要保存都服务器的数据
|
||||
* @param item
|
||||
* @returns
|
||||
*/
|
||||
export const pickRouterViewData = (item: RouterViewItem) => {
|
||||
const { question, action, response, ...rest } = item;
|
||||
if (rest.type === 'api') {
|
||||
if (rest.api) {
|
||||
delete rest.api.query;
|
||||
}
|
||||
}
|
||||
if (rest.type === 'worker') {
|
||||
if (rest.worker) {
|
||||
delete rest.worker.worker;
|
||||
}
|
||||
}
|
||||
if (rest.type === 'context') {
|
||||
if (rest.context) {
|
||||
delete rest.context.router;
|
||||
}
|
||||
}
|
||||
return rest
|
||||
}
|
||||
/**
|
||||
* 注入 js 的url地址,使用importScripts加载
|
||||
*/
|
||||
@@ -91,58 +128,63 @@ export class QueryProxy {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
async initRouterViewQuery() {
|
||||
initRouterViewQuery() {
|
||||
this.routerViewItems = this.routerViewItems.map(item => {
|
||||
if (item.type === 'api' && item.api?.url) {
|
||||
const url = item.api.url;
|
||||
if (item?.api?.query) return item;
|
||||
item['api'] = { url: url, query: new Query({ url: url }) };
|
||||
}
|
||||
if (item.type === 'worker' && item.worker?.url) {
|
||||
let viewItem = item as RouterViewWorker;
|
||||
if (!item.worker?.workerOptions?.type) {
|
||||
item.worker.workerOptions = { ...item.worker.workerOptions, type: 'module' };
|
||||
}
|
||||
if (item.worker.worker) {
|
||||
return item;
|
||||
}
|
||||
let worker: Worker | SharedWorker | ServiceWorker | undefined = undefined;
|
||||
if (item.worker.type === 'SharedWorker') {
|
||||
worker = new SharedWorker(item.worker.url, item.worker.workerOptions);
|
||||
worker.port.start();
|
||||
} else if (viewItem.worker.type === 'serviceWorker') {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register(viewItem.worker.url, item.worker.workerOptions).then(function (registration) {
|
||||
console.debug('注册serviceWorker成功 ', registration.scope);
|
||||
}, function (err) {
|
||||
console.debug('注册 serviceWorker 失败: ', err);
|
||||
});
|
||||
} else {
|
||||
console.warn('当前浏览器不支持serviceWorker');
|
||||
}
|
||||
} else {
|
||||
worker = new Worker(viewItem.worker.url, item.worker.workerOptions);
|
||||
}
|
||||
viewItem['worker']['worker'] = worker;
|
||||
}
|
||||
if (item.type === 'context' && item.context?.key) {
|
||||
if (item.context?.router) {
|
||||
return item;
|
||||
}
|
||||
// @ts-ignore
|
||||
const context = globalThis['context'] || {}
|
||||
const router = context[item.context.key] as QueryRouterServer;
|
||||
if (router) {
|
||||
item['context']['router'] = router;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
return this.initRouterView(item);
|
||||
}).filter(item => {
|
||||
const enabled = item.enabled ?? true;
|
||||
return enabled;
|
||||
});
|
||||
}
|
||||
|
||||
initRouterView(item: RouterViewItem) {
|
||||
if (item.type === 'api' && item.api?.url) {
|
||||
const url = item.api.url;
|
||||
if (item?.api?.query) return item;
|
||||
item['api'] = { url: url, query: new Query({ url: url }) };
|
||||
}
|
||||
if (item.type === 'worker' && item.worker?.url) {
|
||||
let viewItem = item as RouterViewWorker;
|
||||
if (!item.worker?.workerOptions?.type) {
|
||||
item.worker.workerOptions = { ...item.worker.workerOptions, type: 'module' };
|
||||
}
|
||||
if (item.worker.worker) {
|
||||
return item;
|
||||
}
|
||||
let worker: Worker | SharedWorker | ServiceWorker | undefined = undefined;
|
||||
if (item.worker.type === 'SharedWorker') {
|
||||
worker = new SharedWorker(item.worker.url, item.worker.workerOptions);
|
||||
worker.port.start();
|
||||
} else if (viewItem.worker.type === 'serviceWorker') {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register(viewItem.worker.url, item.worker.workerOptions).then(function (registration) {
|
||||
console.debug('注册serviceWorker成功 ', registration.scope);
|
||||
}, function (err) {
|
||||
console.debug('注册 serviceWorker 失败: ', err);
|
||||
});
|
||||
} else {
|
||||
console.warn('当前浏览器不支持serviceWorker');
|
||||
}
|
||||
} else {
|
||||
worker = new Worker(viewItem.worker.url, item.worker.workerOptions);
|
||||
}
|
||||
viewItem['worker']['worker'] = worker;
|
||||
}
|
||||
if (item.type === 'context' && item.context?.key) {
|
||||
if (item.context?.router) {
|
||||
return item;
|
||||
}
|
||||
// @ts-ignore
|
||||
const context = globalThis['context'] || {}
|
||||
const router = context[item.context.key] as QueryRouterServer;
|
||||
if (router) {
|
||||
item['context']['router'] = router;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化路由
|
||||
* @returns
|
||||
@@ -248,7 +290,35 @@ export class QueryProxy {
|
||||
generateId() {
|
||||
return 'route_' + Math.random().toString(36).substring(2, 9);
|
||||
}
|
||||
async initWorker(item?: RouterViewWorker) {
|
||||
async callWorker(msg: any, viewItem: RouterViewWorker['worker']): Promise<Result> {
|
||||
const that = this;
|
||||
const requestId = this.generateId();
|
||||
const worker = viewItem?.worker;
|
||||
if (!worker) {
|
||||
return { code: 500, message: 'Worker未初始化' };
|
||||
}
|
||||
let port: MessagePort | Worker | ServiceWorker;
|
||||
if (viewItem.type === 'SharedWorker') {
|
||||
port = (worker as SharedWorker).port;
|
||||
} else {
|
||||
port = worker as Worker | ServiceWorker;
|
||||
}
|
||||
port.postMessage({
|
||||
...msg,
|
||||
requestId: requestId,
|
||||
})
|
||||
return new Promise((resolve) => {
|
||||
const timer = setTimeout(() => {
|
||||
that.emitter.removeAllListeners(requestId);
|
||||
resolve({ code: 500, message: '请求超时' });
|
||||
}, 3 * 60 * 1000); // 3分钟超时
|
||||
that.emitter.once(requestId, (res: any) => {
|
||||
clearTimeout(timer);
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
async initWorker(item?: RouterViewWorker, initRoutes: boolean = true) {
|
||||
const that = this;
|
||||
if (!item?.worker?.url) {
|
||||
console.warn('Worker URL not provided');
|
||||
@@ -278,33 +348,10 @@ export class QueryProxy {
|
||||
} else {
|
||||
(worker as Worker).onmessage = callResponse;
|
||||
}
|
||||
const callWorker = async (msg: any, viewItem: RouterViewWorker['worker']): Promise<Result> => {
|
||||
const requestId = this.generateId();
|
||||
const worker = viewItem?.worker;
|
||||
if (!worker) {
|
||||
return { code: 500, message: 'Worker未初始化' };
|
||||
}
|
||||
let port: MessagePort | Worker | ServiceWorker;
|
||||
if (viewItem.type === 'SharedWorker') {
|
||||
port = (worker as SharedWorker).port;
|
||||
} else {
|
||||
port = worker as Worker | ServiceWorker;
|
||||
}
|
||||
port.postMessage({
|
||||
...msg,
|
||||
requestId: requestId,
|
||||
})
|
||||
return new Promise((resolve) => {
|
||||
const timer = setTimeout(() => {
|
||||
that.emitter.removeAllListeners(requestId);
|
||||
resolve({ code: 500, message: '请求超时' });
|
||||
}, 3 * 60 * 1000); // 3分钟超时
|
||||
that.emitter.once(requestId, (res: any) => {
|
||||
clearTimeout(timer);
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
if (!initRoutes) {
|
||||
return;
|
||||
}
|
||||
const callWorker = this.callWorker.bind(this);
|
||||
|
||||
const res = await callWorker({
|
||||
path: "router",
|
||||
@@ -393,6 +440,43 @@ export class QueryProxy {
|
||||
async run(msg: { id?: string, path?: string, key?: string }) {
|
||||
return await this.router.run(msg);
|
||||
}
|
||||
|
||||
async runByRouteView(routeView: RouterViewItem) {
|
||||
if (routeView.response) {
|
||||
return routeView;
|
||||
}
|
||||
const item = this.initRouterView(routeView);
|
||||
if (item.type === 'api' && item.api?.url) {
|
||||
const query = item.api.query!;
|
||||
const res = await query.post<any>(item.action || {});
|
||||
item.response = res;
|
||||
return item;
|
||||
} else if (item.type === 'api') {
|
||||
item.response = { code: 500, message: 'API URL未配置' };
|
||||
return item;
|
||||
}
|
||||
if (item.type === 'context' && item.context?.router) {
|
||||
const router = item.context.router;
|
||||
const res = await router.run(item.action || {});
|
||||
item.response = res;
|
||||
return item;
|
||||
}
|
||||
if (item.type === 'page') {
|
||||
await this.initPage(item);
|
||||
const res = await this.router.run(item.action || {});
|
||||
item.response = res;
|
||||
return item;
|
||||
}
|
||||
if (item.type === 'worker' && item.worker?.worker) {
|
||||
await this.initWorker(item, false);
|
||||
const callWorker = this.callWorker.bind(this);
|
||||
const res = await callWorker(item.action || {}, item.worker);
|
||||
item.response = res;
|
||||
return item;
|
||||
}
|
||||
item.response = { code: 500, message: '无法处理的路由类型' };
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
type RouterItem = {
|
||||
|
||||
Reference in New Issue
Block a user