⚡️reduce the invocation times with next tick in sandbox to make qiankun performance in control (#1629)
This commit is contained in:
parent
9e4274e3f8
commit
d7e96a02ae
|
|
@ -3,6 +3,7 @@ import {
|
||||||
getDefaultTplWrapper,
|
getDefaultTplWrapper,
|
||||||
getWrapperId,
|
getWrapperId,
|
||||||
getXPathForElement,
|
getXPathForElement,
|
||||||
|
nextTask,
|
||||||
sleep,
|
sleep,
|
||||||
validateExportLifecycle,
|
validateExportLifecycle,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
@ -116,3 +117,20 @@ test('should getXPathForElement work well', () => {
|
||||||
const xpath1 = getXPathForElement(virtualDOM, document);
|
const xpath1 = getXPathForElement(virtualDOM, document);
|
||||||
expect(xpath1).toBeUndefined();
|
expect(xpath1).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should nextTick just executed once in one task context', async () => {
|
||||||
|
let counter = 0;
|
||||||
|
nextTask(() => ++counter);
|
||||||
|
nextTask(() => ++counter);
|
||||||
|
nextTask(() => ++counter);
|
||||||
|
nextTask(() => ++counter);
|
||||||
|
await sleep(0);
|
||||||
|
expect(counter).toBe(1);
|
||||||
|
|
||||||
|
await sleep(0);
|
||||||
|
nextTask(() => ++counter);
|
||||||
|
await sleep(0);
|
||||||
|
nextTask(() => ++counter);
|
||||||
|
await sleep(0);
|
||||||
|
expect(counter).toBe(3);
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ declare global {
|
||||||
__POWERED_BY_QIANKUN__?: boolean;
|
__POWERED_BY_QIANKUN__?: boolean;
|
||||||
__INJECTED_PUBLIC_PATH_BY_QIANKUN__?: string;
|
__INJECTED_PUBLIC_PATH_BY_QIANKUN__?: string;
|
||||||
__QIANKUN_DEVELOPMENT__?: boolean;
|
__QIANKUN_DEVELOPMENT__?: boolean;
|
||||||
|
Zone?: CallableFunction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
import type { SandBox } from '../interfaces';
|
import type { SandBox } from '../interfaces';
|
||||||
import { SandBoxType } from '../interfaces';
|
import { SandBoxType } from '../interfaces';
|
||||||
import { nextTick } from '../utils';
|
import { nextTask } from '../utils';
|
||||||
import { getTargetValue, setCurrentRunningSandboxProxy } from './common';
|
import { getTargetValue, setCurrentRunningSandboxProxy } from './common';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -215,13 +215,13 @@ export default class ProxySandbox implements SandBox {
|
||||||
},
|
},
|
||||||
|
|
||||||
get(target: FakeWindow, p: PropertyKey): any {
|
get(target: FakeWindow, p: PropertyKey): any {
|
||||||
if (p === Symbol.unscopables) return unscopables;
|
|
||||||
|
|
||||||
setCurrentRunningSandboxProxy(proxy);
|
setCurrentRunningSandboxProxy(proxy);
|
||||||
// FIXME if you have any other good ideas
|
// FIXME if you have any other good ideas
|
||||||
// remove the mark in next tick, thus we can identify whether it in micro app or not
|
// remove the mark in next tick, thus we can identify whether it in micro app or not
|
||||||
// this approach is just a workaround, it could not cover all complex cases, such as the micro app runs in the same task context with master in some case
|
// this approach is just a workaround, it could not cover all complex cases, such as the micro app runs in the same task context with master in some case
|
||||||
nextTick(() => setCurrentRunningSandboxProxy(null));
|
nextTask(() => setCurrentRunningSandboxProxy(null));
|
||||||
|
|
||||||
|
if (p === Symbol.unscopables) return unscopables;
|
||||||
|
|
||||||
// avoid who using window.window or window.self to escape the sandbox environment to touch the really window
|
// avoid who using window.window or window.self to escape the sandbox environment to touch the really window
|
||||||
// see https://github.com/eligrey/FileSaver.js/blob/master/src/FileSaver.js#L13
|
// see https://github.com/eligrey/FileSaver.js/blob/master/src/FileSaver.js#L13
|
||||||
|
|
|
||||||
18
src/utils.ts
18
src/utils.ts
|
|
@ -14,12 +14,24 @@ export function sleep(ms: number) {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Promise.then might be synchronized in Zone.js context, we need to use setTimeout instead to mock next tick.
|
||||||
|
const nextTick: (cb: () => void) => void =
|
||||||
|
typeof window.Zone === 'function' ? setTimeout : (cb) => Promise.resolve().then(cb);
|
||||||
|
|
||||||
|
let globalTaskPending = false;
|
||||||
/**
|
/**
|
||||||
* run a callback after next tick
|
* Run a callback before next task executing, and the invocation is idempotent in every singular task
|
||||||
|
* That means even we called nextTask multi times in one task, only the first callback will be pushed to nextTick to be invoked.
|
||||||
* @param cb
|
* @param cb
|
||||||
*/
|
*/
|
||||||
export function nextTick(cb: () => void): void {
|
export function nextTask(cb: () => void): void {
|
||||||
Promise.resolve().then(cb);
|
if (!globalTaskPending) {
|
||||||
|
globalTaskPending = true;
|
||||||
|
nextTick(() => {
|
||||||
|
cb();
|
||||||
|
globalTaskPending = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const fnRegexCheckCacheMap = new WeakMap<any | FunctionConstructor, boolean>();
|
const fnRegexCheckCacheMap = new WeakMap<any | FunctionConstructor, boolean>();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user