fix(editor): 新增service方法串行调用问题,解决连续快速拖动导致更新节点错乱问题

This commit is contained in:
roymondchen 2022-04-07 14:47:19 +08:00 committed by jia000
parent 9746bab435
commit b8d352a885
2 changed files with 93 additions and 42 deletions

View File

@ -24,6 +24,46 @@ const methodName = (prefix: string, name: string) => `${prefix}${name[0].toUpper
const isError = (error: any): boolean => Object.prototype.toString.call(error) === '[object Error]';
const doAction = async (
args: any[],
scope: any,
sourceMethod: any,
beforeMethodName: string,
afterMethodName: string,
fn: (args: any[], next?: Function | undefined) => Promise<void>,
) => {
try {
let beforeArgs = args;
for (const beforeMethod of scope.pluginOptionsList[beforeMethodName]) {
let beforeReturnValue = (await beforeMethod(...beforeArgs)) || [];
if (isError(beforeReturnValue)) throw beforeReturnValue;
if (!Array.isArray(beforeReturnValue)) {
beforeReturnValue = [beforeReturnValue];
}
beforeArgs = beforeArgs.map((v: any, index: number) => {
if (typeof beforeReturnValue[index] === 'undefined') return v;
return beforeReturnValue[index];
});
}
let returnValue: any = await fn(beforeArgs, sourceMethod.bind(scope));
for (const afterMethod of scope.pluginOptionsList[afterMethodName]) {
returnValue = await afterMethod(...beforeArgs, returnValue);
if (isError(returnValue)) throw returnValue;
}
return returnValue;
} catch (error) {
throw error;
}
};
/**
* Class进行扩展
* 1
@ -74,8 +114,10 @@ const isError = (error: any): boolean => Object.prototype.toString.call(error) =
export default class extends EventEmitter {
private pluginOptionsList: Record<string, Function[]> = {};
private middleware: Record<string, Function[]> = {};
private taskList: (() => Promise<void>)[] = [];
private doingTask = false;
constructor(methods: string[]) {
constructor(methods: string[] = [], serialMethods: string[] = []) {
super();
methods.forEach((propertyName: string) => {
@ -93,32 +135,28 @@ export default class extends EventEmitter {
const fn = compose(this.middleware[propertyName]);
Object.defineProperty(scope, propertyName, {
value: async (...args: any[]) => {
let beforeArgs = args;
if (!serialMethods.includes(propertyName)) {
return doAction(args, scope, sourceMethod, beforeMethodName, afterMethodName, fn);
}
for (const beforeMethod of this.pluginOptionsList[beforeMethodName]) {
let beforeReturnValue = (await beforeMethod(...beforeArgs)) || [];
if (isError(beforeReturnValue)) throw beforeReturnValue;
if (!Array.isArray(beforeReturnValue)) {
beforeReturnValue = [beforeReturnValue];
}
beforeArgs = beforeArgs.map((v: any, index: number) => {
if (typeof beforeReturnValue[index] === 'undefined') return v;
return beforeReturnValue[index];
// 由于async await所以会出现函数执行到await时让出线程导致执行顺序出错例如调用了select(1) -> update -> select(2)这个时候就有可能出现update了2
// 这里保证函数调用严格按顺序执行;
const promise = new Promise<any>((resolve, reject) => {
this.taskList.push(async () => {
try {
const value = await doAction(args, scope, sourceMethod, beforeMethodName, afterMethodName, fn);
resolve(value);
} catch (e) {
reject(e);
}
});
});
if (!this.doingTask) {
this.doTask();
}
let returnValue = await fn(beforeArgs, sourceMethod.bind(scope));
for (const afterMethod of this.pluginOptionsList[afterMethodName]) {
returnValue = await afterMethod(...beforeArgs, returnValue);
if (isError(returnValue)) throw returnValue;
}
return returnValue;
return promise;
},
});
});
@ -135,4 +173,14 @@ export default class extends EventEmitter {
if (typeof method === 'function') this.pluginOptionsList[methodName].push(method);
});
}
private async doTask() {
this.doingTask = true;
let task = this.taskList.shift();
while (task) {
await task();
task = this.taskList.shift();
}
this.doingTask = false;
}
}

View File

@ -57,21 +57,25 @@ class Editor extends BaseService {
});
constructor() {
super([
'getLayout',
'select',
'add',
'remove',
'update',
'sort',
'copy',
'paste',
'alignCenter',
'moveLayer',
'undo',
'redo',
'highlight',
]);
super(
[
'getLayout',
'select',
'add',
'remove',
'update',
'sort',
'copy',
'paste',
'alignCenter',
'moveLayer',
'undo',
'redo',
'highlight',
],
// 需要注意循环依赖问题,如果函数间有相互调用的话,不能设置为串行调用
['select', 'update', 'moveLayer'],
);
}
/**
@ -194,8 +198,8 @@ class Editor extends BaseService {
*/
public highlight(config: MNode | Id): void {
const { node } = this.selectedConfigExceptionHandler(config);
const currentHighligtNode = this.get('highlightNode');
if (currentHighligtNode === node) return;
const currentHighlightNode = this.get('highlightNode');
if (currentHighlightNode === node) return;
this.set('highlightNode', node);
}
@ -335,10 +339,9 @@ class Editor extends BaseService {
if (`${newConfig.id}` === `${this.get('node').id}`) {
this.set('node', newConfig);
this.get<StageCore>('stage')?.update({ config: cloneDeep(newConfig), root: this.get('root') });
}
this.get<StageCore>('stage')?.update({ config: cloneDeep(newConfig), root: this.get('root') });
if (newConfig.type === NodeType.PAGE) {
this.set('page', newConfig);
}