feat(editor): dsl初始化时收集依赖使用worker

This commit is contained in:
roymondchen 2025-05-06 19:59:27 +08:00
parent 9252822c58
commit 179b797c5c
5 changed files with 136 additions and 25 deletions

View File

@ -278,20 +278,21 @@ export const initServiceEvents = (
}); });
}; };
const collectIdle = (nodes: MComponent[], deep: boolean, type?: DepTargetType) => const getPageIdByNode = (node: MComponent) => {
Promise.all( let pageId: Id | undefined;
nodes.map((node) => {
let pageId: Id | undefined;
if (isPage(node)) { if (isPage(node)) {
pageId = node.id; pageId = node.id;
} else { } else {
const info = editorService.getNodeInfo(node.id); const info = editorService.getNodeInfo(node.id);
pageId = info.page?.id; pageId = info.page?.id;
} }
return depService.collectIdle([node], { pageId }, deep, type);
}), return pageId;
); };
const collectIdle = (nodes: MComponent[], deep: boolean, type?: DepTargetType) =>
Promise.all(nodes.map((node) => depService.collectIdle([node], { pageId: getPageIdByNode(node) }, deep, type)));
watch( watch(
() => editorService.get('stage'), () => editorService.get('stage'),
@ -338,7 +339,8 @@ export const initServiceEvents = (
if (Array.isArray(value.items)) { if (Array.isArray(value.items)) {
depService.clearIdleTasks(); depService.clearIdleTasks();
collectIdle(value.items, true).then(() => {
(typeof Worker === 'undefined' ? collectIdle(value.items, true) : depService.collectByWorker(value)).then(() => {
updateStageNodes(value.items); updateStageNodes(value.items);
}); });
} else { } else {
@ -629,16 +631,12 @@ export const initServiceEvents = (
root.dataSourceDeps = {}; root.dataSourceDeps = {};
} }
root.dataSourceDeps[target.id] = target.deps; root.dataSourceDeps[target.id] = target.deps;
} } else if (target.type === DepTargetType.DATA_SOURCE_COND) {
if (target.type === DepTargetType.DATA_SOURCE_COND) {
if (!root.dataSourceCondDeps) { if (!root.dataSourceCondDeps) {
root.dataSourceCondDeps = {}; root.dataSourceCondDeps = {};
} }
root.dataSourceCondDeps[target.id] = target.deps; root.dataSourceCondDeps[target.id] = target.deps;
} } else if (target.type === DepTargetType.DATA_SOURCE_METHOD) {
if (target.type === DepTargetType.DATA_SOURCE_METHOD) {
if (!root.dataSourceMethodDeps) { if (!root.dataSourceMethodDeps) {
root.dataSourceMethodDeps = {}; root.dataSourceMethodDeps = {};
} }

View File

@ -17,12 +17,14 @@
*/ */
import { reactive, shallowReactive } from 'vue'; import { reactive, shallowReactive } from 'vue';
import { throttle } from 'lodash-es'; import { throttle } from 'lodash-es';
import serialize from 'serialize-javascript';
import type { DepExtendedData, Id, MNode, Target, TargetNode } from '@tmagic/core'; import type { DepData, DepExtendedData, Id, MApp, MNode, Target, TargetNode } from '@tmagic/core';
import { DepTargetType, Watcher } from '@tmagic/core'; import { DepTargetType, traverseTarget, Watcher } from '@tmagic/core';
import { isPage } from '@tmagic/utils'; import { isPage } from '@tmagic/utils';
import { IdleTask } from '@editor/utils/idle-task'; import { IdleTask } from '@editor/utils/dep/idle-task';
import Work from '@editor/utils/dep/worker.ts?worker&inline';
import BaseService from './BaseService'; import BaseService from './BaseService';
@ -50,6 +52,8 @@ class Dep extends BaseService {
private watcher = new Watcher({ initialTargets: reactive({}) }); private watcher = new Watcher({ initialTargets: reactive({}) });
private waitingWorker?: Promise<void>;
constructor() { constructor() {
super(); super();
@ -114,7 +118,11 @@ class Dep extends BaseService {
this.emit('ds-collected', nodes, deep); this.emit('ds-collected', nodes, deep);
} }
public collectIdle(nodes: MNode[], depExtendedData: DepExtendedData = {}, deep = false, type?: DepTargetType) { public async collectIdle(nodes: MNode[], depExtendedData: DepExtendedData = {}, deep = false, type?: DepTargetType) {
if (this.waitingWorker) {
await this.waitingWorker;
}
this.set('collecting', true); this.set('collecting', true);
let startTask = false; let startTask = false;
this.watcher.collectByCallback(nodes, type, ({ node, target }) => { this.watcher.collectByCallback(nodes, type, ({ node, target }) => {
@ -141,6 +149,48 @@ class Dep extends BaseService {
}); });
} }
public collectByWorker(dsl: MApp) {
this.set('collecting', true);
const { promise, resolve: waitingResolve } = Promise.withResolvers<void>();
this.waitingWorker = promise;
return new Promise<Record<string, Record<string, DepData>>>((resolve) => {
const worker = new Work();
worker.postMessage({
dsl: serialize(dsl),
});
worker.onmessage = (e) => {
resolve(e.data);
};
worker.onerror = () => {
resolve({});
};
}).then((depsData) => {
traverseTarget(this.watcher.getTargetsList(), (target) => {
if (depsData[target.type]?.[target.id]) {
target.deps = reactive(depsData[target.type][target.id]);
if (target.type === DepTargetType.DATA_SOURCE && dsl.dataSourceDeps) {
dsl.dataSourceDeps[target.id] = target.deps;
} else if (target.type === DepTargetType.DATA_SOURCE_COND && dsl.dataSourceCondDeps) {
dsl.dataSourceCondDeps[target.id] = target.deps;
} else if (target.type === DepTargetType.DATA_SOURCE_METHOD) {
dsl.dataSourceMethodDeps[target.id] = target.deps;
}
}
});
this.set('collecting', false);
this.emit('collected', dsl.items, true);
this.emit('ds-collected', dsl.items, true);
waitingResolve();
return depsData;
});
}
public collectNode(node: MNode, target: Target, depExtendedData: DepExtendedData = {}, deep = false) { public collectNode(node: MNode, target: Target, depExtendedData: DepExtendedData = {}, deep = false) {
// 先删除原有依赖,重新收集 // 先删除原有依赖,重新收集
if (isPage(node)) { if (isPage(node)) {

View File

@ -0,0 +1,63 @@
import {
createCodeBlockTarget,
createDataSourceCondTarget,
createDataSourceMethodTarget,
createDataSourceTarget,
type DepData,
DepTargetType,
type Id,
type MApp,
traverseTarget,
Watcher,
} from '@tmagic/core';
import { error } from '../logger';
onmessage = (e) => {
const watcher = new Watcher({ initialTargets: {} });
const { dsl } = e.data;
try {
// eslint-disable-next-line no-eval
const mApp: MApp = eval(`(${dsl})`);
if (!mApp) {
postMessage({});
}
if (mApp.codeBlocks) {
for (const [id, code] of Object.entries(mApp.codeBlocks)) {
watcher.addTarget(createCodeBlockTarget(id, code));
}
}
if (mApp.dataSources) {
for (const ds of mApp.dataSources) {
watcher.addTarget(createDataSourceTarget(ds, {}));
watcher.addTarget(createDataSourceMethodTarget(ds, {}));
watcher.addTarget(createDataSourceCondTarget(ds, {}));
}
}
watcher.collectByCallback(mApp.items, undefined, ({ node, target }) => {
watcher.collectItem(node, target, { pageId: node.id }, true);
});
const data: Record<string, Record<Id, DepData>> = {
[DepTargetType.DATA_SOURCE]: {},
[DepTargetType.DATA_SOURCE_METHOD]: {},
[DepTargetType.DATA_SOURCE_COND]: {},
[DepTargetType.CODE_BLOCK]: {},
};
traverseTarget(watcher.getTargetsList(), (target) => {
data[target.type][target.id] = target.deps;
});
postMessage(data);
} catch (e: any) {
error(e);
postMessage({});
}
};

View File

@ -22,7 +22,7 @@ export * from './logger';
export * from './editor'; export * from './editor';
export * from './operator'; export * from './operator';
export * from './data-source'; export * from './data-source';
export * from './idle-task'; export * from './dep/idle-task';
export * from './scroll-viewer'; export * from './scroll-viewer';
export * from './tree'; export * from './tree';
export * from './undo-redo'; export * from './undo-redo';