From 6dc007388bb28e6501bcb026fce1e2881b87bd82 Mon Sep 17 00:00:00 2001 From: roymondchen Date: Mon, 28 Apr 2025 17:25:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(core):=20=E6=B7=BB=E5=8A=A0error=20hander?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/App.ts | 41 +++++++++++++++++++++++--- packages/core/src/EventHelper.ts | 49 ++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 19 deletions(-) diff --git a/packages/core/src/App.ts b/packages/core/src/App.ts index 52da9717..3cf55fba 100644 --- a/packages/core/src/App.ts +++ b/packages/core/src/App.ts @@ -20,8 +20,8 @@ import { EventEmitter } from 'events'; import { isEmpty } from 'lodash-es'; -import { createDataSourceManager, DataSourceManager, ObservedDataClass } from '@tmagic/data-source'; -import type { CodeBlockDSL, Id, JsEngine, MApp, RequestFunction } from '@tmagic/schema'; +import { createDataSourceManager, type DataSource, DataSourceManager, ObservedDataClass } from '@tmagic/data-source'; +import type { CodeBlockDSL, DataSourceSchema, Id, JsEngine, MApp, RequestFunction } from '@tmagic/schema'; import Env from './Env'; import EventHelper from './EventHelper'; @@ -31,6 +31,12 @@ import Node from './Node'; import Page from './Page'; import { transformStyle as defaultTransformStyle } from './utils'; +export type ErrorHandler = ( + err: Error, + node: DataSource | Node | undefined, + info: Record, +) => void; + export interface AppOptionsConfig { ua?: string; env?: Env; @@ -46,6 +52,7 @@ export interface AppOptionsConfig { transformStyle?: (style: Record) => Record; request?: RequestFunction; DataSourceObservedData?: ObservedDataClass; + errorHandler?: ErrorHandler; } class App extends EventEmitter { @@ -70,6 +77,7 @@ class App extends EventEmitter { public request?: RequestFunction; public transformStyle: (style: Record) => Record; public eventHelper?: EventHelper; + public errorHandler?: ErrorHandler; private flexible?: Flexible; @@ -82,6 +90,8 @@ class App extends EventEmitter { this.setEnv(options.ua); } + this.errorHandler = options.errorHandler; + // 代码块描述内容在dsl codeBlocks字段 this.codeDsl = options.config?.codeBlocks; options.platform && (this.platform = options.platform); @@ -259,7 +269,15 @@ class App extends EventEmitter { if (!codeId || isEmpty(this.codeDsl)) return; const content = this.codeDsl?.[codeId]?.content; if (typeof content === 'function') { - await content({ app: this, params, eventParams: args, flowState }); + try { + await content({ app: this, params, eventParams: args, flowState }); + } catch (e: any) { + if (this.errorHandler) { + this.errorHandler(e, undefined, { type: 'run-code', codeId, params, eventParams: args, flowState }); + } else { + throw e; + } + } } } @@ -283,7 +301,15 @@ class App extends EventEmitter { if (!method) return; if (typeof method.content === 'function') { - await method.content({ app: this, params, dataSource, eventParams: args, flowState }); + try { + await method.content({ app: this, params, dataSource, eventParams: args, flowState }); + } catch (e: any) { + if (this.errorHandler) { + this.errorHandler(e, dataSource, { type: 'data-source-method', params, eventParams: args, flowState }); + } else { + throw e; + } + } } } @@ -295,6 +321,13 @@ class App extends EventEmitter { this.flexible = undefined; this.eventHelper?.destroy(); + + this.dsl = undefined; + + this.dataSourceManager?.destroy(); + this.dataSourceManager = undefined; + this.codeDsl = undefined; + this.components.clear(); } } diff --git a/packages/core/src/EventHelper.ts b/packages/core/src/EventHelper.ts index b329bb2e..496a1a09 100644 --- a/packages/core/src/EventHelper.ts +++ b/packages/core/src/EventHelper.ts @@ -53,6 +53,8 @@ export default class EventHelper extends EventEmitter { public destroy() { this.removeNodeEvents(); this.removeAllListeners(); + this.nodeEventList.clear(); + this.dataSourceEventList.clear(); } public bindNodeEvents(node: TMagicNode) { @@ -147,6 +149,7 @@ export default class EventHelper extends EventEmitter { */ private async eventHandler(config: EventConfig | number, fromCpt: TMagicNode | DataSource | undefined, args: any[]) { const eventConfig = typeof config === 'number' ? (fromCpt as TMagicNode).events[config] : config; + if (has(eventConfig, 'actions')) { // EventConfig类型 const flowState = new FlowState(); @@ -163,8 +166,16 @@ export default class EventHelper extends EventEmitter { } flowState.reset(); } else { - // 兼容DeprecatedEventConfig类型 组件动作 - await this.compActionHandler(eventConfig as unknown as CompItemConfig, fromCpt as TMagicNode, args); + try { + // 兼容DeprecatedEventConfig类型 组件动作 + await this.compActionHandler(eventConfig as unknown as CompItemConfig, fromCpt as TMagicNode, args); + } catch (e: any) { + if (this.app.errorHandler) { + this.app.errorHandler(e, fromCpt, { type: 'action-handler', config: eventConfig, ...args }); + } else { + throw e; + } + } } } @@ -174,20 +185,28 @@ export default class EventHelper extends EventEmitter { args: any[], flowState: FlowState, ) { - if (actionItem.actionType === ActionType.COMP) { - const compActionItem = actionItem as CompItemConfig; - // 组件动作 - await this.compActionHandler(compActionItem, fromCpt, args); - } else if (actionItem.actionType === ActionType.CODE) { - const codeActionItem = actionItem as CodeItemConfig; - // 执行代码块 - await this.app.runCode(codeActionItem.codeId, codeActionItem.params || {}, args, flowState); - } else if (actionItem.actionType === ActionType.DATA_SOURCE) { - const dataSourceActionItem = actionItem as DataSourceItemConfig; + try { + if (actionItem.actionType === ActionType.COMP) { + const compActionItem = actionItem as CompItemConfig; + // 组件动作 + await this.compActionHandler(compActionItem, fromCpt, args); + } else if (actionItem.actionType === ActionType.CODE) { + const codeActionItem = actionItem as CodeItemConfig; + // 执行代码块 + await this.app.runCode(codeActionItem.codeId, codeActionItem.params || {}, args, flowState); + } else if (actionItem.actionType === ActionType.DATA_SOURCE) { + const dataSourceActionItem = actionItem as DataSourceItemConfig; - const [dsId, methodName] = dataSourceActionItem.dataSourceMethod; + const [dsId, methodName] = dataSourceActionItem.dataSourceMethod; - await this.app.runDataSourceMethod(dsId, methodName, dataSourceActionItem.params || {}, args, flowState); + await this.app.runDataSourceMethod(dsId, methodName, dataSourceActionItem.params || {}, args, flowState); + } + } catch (e: any) { + if (this.app.errorHandler) { + this.app.errorHandler(e, fromCpt, { type: 'action-handler', config: actionItem, flowState, ...args }); + } else { + throw e; + } } } @@ -206,7 +225,7 @@ export default class EventHelper extends EventEmitter { } const toNode = this.app.getNode(to); - if (!toNode) throw `ID为${to}的组件不存在`; + if (!toNode) throw new Error(`ID为${to}的组件不存在`); if (toNode.instance) { if (typeof toNode.instance[methodName] === 'function') {