⚡️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,
|
||||
getWrapperId,
|
||||
getXPathForElement,
|
||||
nextTask,
|
||||
sleep,
|
||||
validateExportLifecycle,
|
||||
} from '../utils';
|
||||
|
|
@ -116,3 +117,20 @@ test('should getXPathForElement work well', () => {
|
|||
const xpath1 = getXPathForElement(virtualDOM, document);
|
||||
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;
|
||||
__INJECTED_PUBLIC_PATH_BY_QIANKUN__?: string;
|
||||
__QIANKUN_DEVELOPMENT__?: boolean;
|
||||
Zone?: CallableFunction;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
import type { SandBox } from '../interfaces';
|
||||
import { SandBoxType } from '../interfaces';
|
||||
import { nextTick } from '../utils';
|
||||
import { nextTask } from '../utils';
|
||||
import { getTargetValue, setCurrentRunningSandboxProxy } from './common';
|
||||
|
||||
/**
|
||||
|
|
@ -215,13 +215,13 @@ export default class ProxySandbox implements SandBox {
|
|||
},
|
||||
|
||||
get(target: FakeWindow, p: PropertyKey): any {
|
||||
if (p === Symbol.unscopables) return unscopables;
|
||||
|
||||
setCurrentRunningSandboxProxy(proxy);
|
||||
// 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
|
||||
// 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
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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
|
||||
*/
|
||||
export function nextTick(cb: () => void): void {
|
||||
Promise.resolve().then(cb);
|
||||
export function nextTask(cb: () => void): void {
|
||||
if (!globalTaskPending) {
|
||||
globalTaskPending = true;
|
||||
nextTick(() => {
|
||||
cb();
|
||||
globalTaskPending = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const fnRegexCheckCacheMap = new WeakMap<any | FunctionConstructor, boolean>();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user