mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-15 10:48:17 +00:00
feat: 透出错误边界捕捉不到的错误
This commit is contained in:
parent
55948e1d3f
commit
f224abffff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-react-provider",
|
"name": "@ali/lowcode-react-provider",
|
||||||
"version": "1.0.6-0",
|
"version": "1.0.6-1",
|
||||||
"description": "React Provider for Runtime",
|
"description": "React Provider for Runtime",
|
||||||
"files": [
|
"files": [
|
||||||
"es",
|
"es",
|
||||||
|
|||||||
@ -32,19 +32,24 @@ export default class LazyComponent extends Component<IProps, IState> {
|
|||||||
const schema = await getPageData();
|
const schema = await getPageData();
|
||||||
this.setState({ schema });
|
this.setState({ schema });
|
||||||
context.emitPageReady();
|
context.emitPageReady();
|
||||||
} catch (error) {
|
} catch (err) {
|
||||||
this.setState({ hasError: true });
|
this.setState({ hasError: true });
|
||||||
|
this.exeAfterCatch(err.message, err.stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidCatch(error: any, errorInfo: any) {
|
exeAfterCatch(error: any, errorInfo?: any) {
|
||||||
const { afterCatch } = app.getErrorBoundary() || {};
|
const { afterCatch } = app.getErrorBoundary() || {};
|
||||||
if (typeof afterCatch === 'function') {
|
if (typeof afterCatch === 'function') {
|
||||||
afterCatch.call(this, error, errorInfo);
|
afterCatch.call(this, error, errorInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidCatch(error: any, errorInfo: any) {
|
||||||
|
this.exeAfterCatch(error, errorInfo);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { schema, hasError } = this.state;
|
const { schema, hasError } = this.state;
|
||||||
if (hasError) {
|
if (hasError) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-runtime",
|
"name": "@ali/lowcode-runtime",
|
||||||
"version": "1.0.6-0",
|
"version": "1.0.6-1",
|
||||||
"description": "Runtime for Ali lowCode engine",
|
"description": "Runtime for Ali lowCode engine",
|
||||||
"files": [
|
"files": [
|
||||||
"es",
|
"es",
|
||||||
|
|||||||
@ -1,383 +1,57 @@
|
|||||||
import { IAppConfig, IUtils, IComponents, HistoryMode } from './runApp';
|
import Container, { ILayoutOptions, IErrorBoundaryConfig } from './container';
|
||||||
import EventEmitter from '@ali/offline-events';
|
import Provider from './provider';
|
||||||
|
import runApp from './runApp';
|
||||||
|
|
||||||
interface IConstants {
|
class App {
|
||||||
[key: string]: any;
|
private container: Container;
|
||||||
}
|
|
||||||
|
|
||||||
interface IComponentMap {
|
|
||||||
componentName: string;
|
|
||||||
package?: string;
|
|
||||||
version?: string;
|
|
||||||
destructuring?: boolean;
|
|
||||||
exportName?: string;
|
|
||||||
subName?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ILayoutConfig {
|
|
||||||
componentName: string;
|
|
||||||
props: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IRouterConfig {
|
|
||||||
[key: string]: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IHistoryConfig {
|
|
||||||
mode: HistoryMode;
|
|
||||||
basement?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IAppData {
|
|
||||||
history?: HistoryMode;
|
|
||||||
layout?: ILayoutConfig;
|
|
||||||
routes?: IRouterConfig;
|
|
||||||
containerId?: string;
|
|
||||||
components?: IComponents;
|
|
||||||
componentsMap?: IComponentMap[];
|
|
||||||
utils?: IUtils;
|
|
||||||
constants?: IConstants;
|
|
||||||
i18n?: I18n;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ComponentProps {
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface JSExpression {
|
|
||||||
type: string;
|
|
||||||
value: string;
|
|
||||||
[key: string]: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DataSourceItem {
|
|
||||||
id: string;
|
|
||||||
isInit: boolean;
|
|
||||||
type: string;
|
|
||||||
options: {
|
|
||||||
uri: string;
|
|
||||||
params: object;
|
|
||||||
method: string;
|
|
||||||
shouldFetch?: string;
|
|
||||||
willFetch?: string;
|
|
||||||
fit?: string;
|
|
||||||
didFetch?: string;
|
|
||||||
};
|
|
||||||
dataHandler: JSExpression;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DataSource {
|
|
||||||
list: DataSourceItem[];
|
|
||||||
dataHandler: JSExpression;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LifeCycles {
|
|
||||||
[key: string]: JSExpression;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Methods {
|
|
||||||
[key: string]: JSExpression;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ComponentModel {
|
|
||||||
id?: string;
|
|
||||||
componentName: string;
|
|
||||||
fileName?: string;
|
|
||||||
props?: ComponentProps;
|
|
||||||
css?: string;
|
|
||||||
dataSource?: DataSource;
|
|
||||||
lifeCycles?: LifeCycles;
|
|
||||||
methods?: Methods;
|
|
||||||
children?: ComponentModel[] | string[];
|
|
||||||
condition?: JSExpression | boolean;
|
|
||||||
loop?: string[];
|
|
||||||
loopArgs?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface I18n {
|
|
||||||
'zh-CN': { [key: string]: string };
|
|
||||||
'en-US': { [key: string]: string };
|
|
||||||
}
|
|
||||||
|
|
||||||
type Locale = 'zh-CN' | 'en-US';
|
|
||||||
|
|
||||||
export default class Provider {
|
|
||||||
emitter: EventEmitter = new EventEmitter();
|
|
||||||
components: IComponents = {};
|
|
||||||
utils: IUtils = {};
|
|
||||||
constants: IConstants = {};
|
|
||||||
routes: IRouterConfig | null = null;
|
|
||||||
layout: ILayoutConfig | null = null;
|
|
||||||
componentsMap: IComponentMap[] = [];
|
|
||||||
history: HistoryMode = 'hash';
|
|
||||||
containerId = '';
|
|
||||||
i18n: I18n | null = null;
|
|
||||||
homePage = '';
|
|
||||||
lazyElementsMap: { [key: string]: any } = {};
|
|
||||||
isSectionalRender = false;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.init();
|
this.container = new Container();
|
||||||
}
|
}
|
||||||
|
|
||||||
async(): Promise<IAppConfig> {
|
run() {
|
||||||
return new Promise(async (resolve, reject) => {
|
runApp();
|
||||||
try {
|
|
||||||
const appData: IAppData = await this.getAppData();
|
|
||||||
if (!appData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { history, layout, routes, containerId, components, componentsMap, utils, constants, i18n } = appData;
|
|
||||||
this.setHistory(history);
|
|
||||||
this.setLayoutConfig(layout);
|
|
||||||
this.setRouterConfig(routes);
|
|
||||||
this.setContainerId(containerId);
|
|
||||||
this.setI18n(i18n);
|
|
||||||
this.registerComponents(components);
|
|
||||||
this.registerComponentsMap(componentsMap);
|
|
||||||
this.registerUtils(utils);
|
|
||||||
this.registerContants(constants);
|
|
||||||
resolve({
|
|
||||||
history: this.getHistory(),
|
|
||||||
components: this.getComponents(),
|
|
||||||
utils: this.getUtils(),
|
|
||||||
containerId: this.getContainerId(),
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
registerRenderer(renderer: any): any {
|
||||||
// 默认 ready,当重载了init时需手动触发 this.ready()
|
this.container.registerRenderer(renderer);
|
||||||
this.ready();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ready(params?: any) {
|
registerLayout(Layout: any, options: ILayoutOptions): any {
|
||||||
if (params && typeof params === 'function') {
|
this.container.registerLayout(Layout, options);
|
||||||
params = params();
|
|
||||||
}
|
|
||||||
this.emitter.emit('ready', params || '');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onReady(cb: (params?: any) => void) {
|
registerLoading(component: any) {
|
||||||
if (!cb || typeof cb !== 'function') {
|
this.container.registerLoading(component);
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.emitter.on('ready', cb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emitPageReady() {
|
registerProvider(CustomProvider: any) {
|
||||||
this.emitter.emit('pageReady');
|
this.container.registerProvider(CustomProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
emitPageEnter() {
|
registerErrorBoundary(config: IErrorBoundaryConfig) {
|
||||||
this.emitter.emit('pageEnter');
|
this.container.registerErrorBoundary(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
emitPageUpdate() {
|
getLayout(componentName: string) {
|
||||||
this.emitter.emit('pageUpdate');
|
return this.container.getLayout(componentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
emitPageLeave() {
|
getRenderer(): any {
|
||||||
this.emitter.emit('pageLeave');
|
return this.container.getRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
onPageReady(cb: (params?: any) => void) {
|
getLoading(): any {
|
||||||
this.emitter.on('pageReady', cb);
|
return this.container.getLoading();
|
||||||
return () => {
|
|
||||||
this.emitter.removeListener('pageReady', cb);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onPageEnter(cb: (params?: any) => void) {
|
getErrorBoundary(): IErrorBoundaryConfig {
|
||||||
this.emitter.on('pageEnter', cb);
|
return this.container.getErrorBoundary();
|
||||||
return () => {
|
|
||||||
this.emitter.removeListener('pageEnter', cb);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onPageUpdate(cb: (params?: any) => void) {
|
getProvider(id?: string): Provider | undefined {
|
||||||
this.emitter.on('pageUpdate', cb);
|
return this.container.getProvider(id);
|
||||||
return () => {
|
|
||||||
this.emitter.removeListener('pageUpdate', cb);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onPageLeave(cb: (params?: any) => void) {
|
|
||||||
this.emitter.on('pageLeave', cb);
|
|
||||||
return () => {
|
|
||||||
this.emitter.removeListener('pageLeave', cb);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
getAppData(): any {
|
|
||||||
throw new Error('Method called "getAppData" not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
getPageData(pageId?: string): any {
|
|
||||||
throw new Error('Method called "getPageData" not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
getLazyComponent(pageId: string, props: any): any {
|
|
||||||
throw new Error('Method called "getLazyComponent" not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 定制构造根组件的逻辑,如切换路由机制
|
|
||||||
createApp() {
|
|
||||||
throw new Error('Method called "createApp" not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
runApp(App: any, config: IAppConfig) {
|
|
||||||
throw new Error('Method called "runApp" not implemented.');
|
|
||||||
}
|
|
||||||
|
|
||||||
registerComponents(components: IComponents | undefined) {
|
|
||||||
if (!components) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.components = components;
|
|
||||||
}
|
|
||||||
|
|
||||||
registerComponentsMap(componentsMap: IComponentMap[] | undefined) {
|
|
||||||
if (!componentsMap) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.componentsMap = componentsMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
registerUtils(utils: IUtils | undefined) {
|
|
||||||
if (!utils) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.utils = utils;
|
|
||||||
}
|
|
||||||
|
|
||||||
registerContants(constants: IConstants | undefined) {
|
|
||||||
if (!constants) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.constants = constants;
|
|
||||||
}
|
|
||||||
|
|
||||||
setLayoutConfig(config: ILayoutConfig | undefined) {
|
|
||||||
if (!config) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.layout = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
setRouterConfig(config: IRouterConfig | undefined) {
|
|
||||||
if (!config) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.routes = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
setHistory(config: HistoryMode | undefined): any {
|
|
||||||
if (!config) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.history = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
setContainerId(id: string | undefined) {
|
|
||||||
if (!id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.containerId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
setI18n(i18n: I18n | undefined) {
|
|
||||||
if (!i18n) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.i18n = i18n;
|
|
||||||
}
|
|
||||||
|
|
||||||
setLazyElement(pageId: string, cache: any) {
|
|
||||||
if (!pageId || !cache) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.lazyElementsMap[pageId] = cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
setHomePage(pageId: string) {
|
|
||||||
if (pageId) {
|
|
||||||
this.homePage = pageId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getComponents() {
|
|
||||||
return this.components;
|
|
||||||
}
|
|
||||||
|
|
||||||
getComponent(name: string) {
|
|
||||||
if (!name) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return this.components[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
getUtils() {
|
|
||||||
return this.utils;
|
|
||||||
}
|
|
||||||
|
|
||||||
getConstants() {
|
|
||||||
return this.constants;
|
|
||||||
}
|
|
||||||
|
|
||||||
getComponentsMap() {
|
|
||||||
return this.componentsMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
getComponentsMapObj() {
|
|
||||||
const compMapArr = this.getComponentsMap();
|
|
||||||
if (!compMapArr || !Array.isArray(compMapArr)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const compMapObj: any = {};
|
|
||||||
compMapArr.forEach((item: IComponentMap) => {
|
|
||||||
if (!item || !item.componentName) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
compMapObj[item.componentName] = item;
|
|
||||||
});
|
|
||||||
return compMapObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLayoutConfig() {
|
|
||||||
return this.layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
getRouterConfig() {
|
|
||||||
return this.routes;
|
|
||||||
}
|
|
||||||
|
|
||||||
getHistory() {
|
|
||||||
return this.history;
|
|
||||||
}
|
|
||||||
|
|
||||||
getContainerId() {
|
|
||||||
return this.containerId || 'App';
|
|
||||||
}
|
|
||||||
|
|
||||||
getI18n(locale?: Locale) {
|
|
||||||
if (!this.i18n) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return locale ? this.i18n[locale] : this.i18n;
|
|
||||||
}
|
|
||||||
|
|
||||||
getHomePage() {
|
|
||||||
return this.homePage;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLazyElement(pageId: string) {
|
|
||||||
if (!pageId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return this.lazyElementsMap[pageId];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default new App();
|
||||||
|
|||||||
@ -36,9 +36,12 @@ export default function runApp() {
|
|||||||
}
|
}
|
||||||
const App = provider.createApp();
|
const App = provider.createApp();
|
||||||
provider.runApp(App, config);
|
provider.runApp(App, config);
|
||||||
}).catch((err) => {
|
}).catch((err: Error) => {
|
||||||
console.error(err.message);
|
console.error(err.message);
|
||||||
const { fallbackUI } = app.getErrorBoundary() || {};
|
const { fallbackUI, afterCatch } = app.getErrorBoundary() || {};
|
||||||
|
if (typeof afterCatch === 'function') {
|
||||||
|
afterCatch(err.message, err.stack);
|
||||||
|
}
|
||||||
if (!fallbackUI) {
|
if (!fallbackUI) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user