Skip to content

Commit 6205e8d

Browse files
author
winjo
committed
fix: 修复 app dispose 报错问题
1 parent 3a3c9d2 commit 6205e8d

6 files changed

Lines changed: 86 additions & 28 deletions

File tree

packages/alex/src/api/createApp.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@ import { IThemeService } from '@ali/ide-theme/lib/common';
1111
import '@ali/ide-i18n/lib/browser';
1212
import '@alipay/alex-i18n';
1313
import '@ali/ide-core-browser/lib/style/index.less';
14+
import { isMonacoLoaded, loadMonaco } from '@ali/ide-monaco/lib/browser/monaco-loader';
15+
import { IEditorDocumentModelService } from '@ali/ide-editor/lib/browser';
16+
import { EditorDocumentModelServiceImpl } from '@ali/ide-editor/lib/browser/doc-model/editor-document-model-service';
17+
import { EditorDocumentModel } from '@ali/ide-editor/lib/browser/doc-model/editor-document-model';
18+
import { FileTreeModelService } from '@ali/ide-file-tree-next/lib/browser/services/file-tree-model.service';
1419
import * as os from 'os';
20+
1521
import { modules } from '../core/modules';
1622
import { IconSlim, IDETheme } from '../core/extensions';
1723
import { mergeConfig, themeStorage } from '../core/utils';
@@ -50,6 +56,13 @@ const getDefaultAppConfig = (): IAppOpts => ({
5056

5157
export const DEFAULT_APP_CONFIG = getDefaultAppConfig();
5258

59+
// 提前加载 monaco 并提前缓存 codeEditorService
60+
loadMonaco();
61+
let codeEditorService: any = null;
62+
isMonacoLoaded()?.then(() => {
63+
codeEditorService = (monaco as any).services.StaticServices.codeEditorService;
64+
});
65+
5366
export function createApp({ appConfig, runtimeConfig }: IConfig): IAppInstance {
5467
const customConfig = typeof appConfig === 'function' ? appConfig() : appConfig;
5568
const opts = mergeConfig(getDefaultAppConfig(), customConfig);
@@ -84,6 +97,29 @@ export function createApp({ appConfig, runtimeConfig }: IConfig): IAppInstance {
8497
(app.injector.get(IThemeService) as IThemeService).onThemeChange((e) => {
8598
themeStorage.set(e.type);
8699
});
100+
// IDE 销毁时,组件会触发 handleTreeBlur,但是 FileContextKey 实例会获取,此时在 dispose 阶段,injector.get(FileContextKey) 会抛出错误
101+
app.injector.get(FileTreeModelService).handleTreeBlur();
102+
};
103+
104+
let destroyed = false;
105+
app.destroy = () => {
106+
if (destroyed) {
107+
return;
108+
}
109+
destroyed = true;
110+
// from acr
111+
const editorDocModelService = app.injector.get(
112+
IEditorDocumentModelService
113+
) as EditorDocumentModelServiceImpl;
114+
for (const instance of Array.from(
115+
editorDocModelService['_modelReferenceManager'].instances.values()
116+
) as EditorDocumentModel[]) {
117+
instance['monacoModel'].dispose();
118+
}
119+
if (codeEditorService) {
120+
codeEditorService._value = null;
121+
}
122+
app.injector.disposeAll();
87123
};
88124

89125
runtimeConfig ??= {};

packages/alex/src/api/renderApp.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export const renderApp = (domElement: HTMLElement, props: IRenderProps) => {
4040
domElement
4141
);
4242
});
43+
44+
return () => {
45+
app.destroy();
46+
};
4347
};
4448

4549
export const AppRenderer: React.FC<IRenderProps> = ({ onLoad, Landing, ...opts }) => {
@@ -68,7 +72,7 @@ export const AppRenderer: React.FC<IRenderProps> = ({ onLoad, Landing, ...opts }
6872
});
6973

7074
return () => {
71-
app.dispose();
75+
app.destroy();
7276
};
7377
}, []);
7478

packages/alex/src/api/types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,14 @@ export interface IConfig {
2020
}
2121

2222
export interface IAppInstance extends ClientApp {
23+
/**
24+
* 启动应用
25+
* @param container 挂载位置
26+
*/
2327
start(container: HTMLElement | IAppRenderer): Promise<void>;
28+
29+
/**
30+
* 销毁应用
31+
*/
32+
destroy(): void;
2433
}

packages/alex/src/integration/startup/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ ReactDOM.render(
8080
// },
8181
// });
8282

83+
// for test
8384
(window as any).destroy = () => {
84-
ReactDOM.render(<div>11</div>, document.getElementById('main'));
85+
ReactDOM.render(<div>destroyed</div>, document.getElementById('main'));
8586
};

packages/core/src/client/index.ts

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ import {
88
import { BasicModule } from '@ali/ide-core-common';
99
import { WSChannelHandler } from '@ali/ide-connection';
1010

11-
import { IEditorDocumentModelService } from '@ali/ide-editor/lib/browser';
12-
import { EditorDocumentModelServiceImpl } from '@ali/ide-editor/lib/browser/doc-model/editor-document-model-service';
13-
import { EditorDocumentModel } from '@ali/ide-editor/lib/browser/doc-model/editor-document-model';
14-
import { isMonacoLoaded } from '@ali/ide-monaco/lib/browser/monaco-loader';
15-
1611
import { FCServiceCenter, ClientPort, initFCService } from '../connection';
1712
import { KaitianExtFsProvider, KtExtFsProviderContribution } from './extension';
1813
import { TextmateLanguageGrammarContribution } from './textmate-language-grammar/index.contribution';
@@ -36,11 +31,6 @@ export { TextmateLanguageGrammarContribution, LanguageGrammarRegistrationService
3631

3732
export type ModuleConstructor = ConstructorOf<BrowserModule>;
3833

39-
let codeEditorService: any = null;
40-
isMonacoLoaded()?.then(() => {
41-
codeEditorService = (monaco as any).services.StaticServices.codeEditorService;
42-
});
43-
4434
@Injectable()
4535
export class ClientModule extends BrowserModule {
4636
providers = [
@@ -65,6 +55,8 @@ export interface IAppOpts extends IClientAppOpts, IServerAppOpts {}
6555
export { IClientAppOpts };
6656

6757
export class ClientApp extends BasicClientApp {
58+
private disposed = false;
59+
6860
constructor(opts: IAppOpts) {
6961
super(opts);
7062
this.initServer(opts);
@@ -99,23 +91,25 @@ export class ClientApp extends BasicClientApp {
9991
return super.start(container, type);
10092
}
10193

102-
public dispose() {
103-
// from acr
104-
// TODO: dispose 会存在报错,需要解决
105-
if (this.injector.hasInstance(IEditorDocumentModelService)) {
106-
const editorDocModelService = this.injector.get(
107-
IEditorDocumentModelService
108-
) as EditorDocumentModelServiceImpl;
109-
for (const instance of Array.from(
110-
editorDocModelService['_modelReferenceManager'].instances.values()
111-
) as EditorDocumentModel[]) {
112-
instance['monacoModel'].dispose();
113-
}
94+
stopContributions() {
95+
if (!this.disposed) {
96+
super.stopContributions();
11497
}
115-
if (codeEditorService) {
116-
codeEditorService._value = null;
98+
}
99+
100+
preventStop() {
101+
if (!this.disposed) {
102+
return super.preventStop();
117103
}
118-
this.injector.disposeAll();
104+
return false;
105+
}
106+
107+
/**
108+
* kaitian 中没有注销注册在 window 上上的事件,在把 IDE 销毁后,此时刷新页面依然会执行事件
109+
* 此时 injector.get 都会报错,因此这里加个状态判断
110+
*/
111+
dispose() {
112+
this.disposed = true;
119113
}
120114
}
121115

packages/core/src/server/core/app.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
ILogService,
88
SupportLogNamespace,
99
StoragePaths,
10+
DisposableCollection,
1011
} from '@ali/ide-core-common';
1112
import { AppConfig, BrowserModule } from '@ali/ide-core-browser';
1213
import { IExtensionBasicMetadata } from '@alipay/alex-shared';
@@ -93,6 +94,8 @@ export class ServerApp implements IServerApp {
9394

9495
public rootFS: RootFS;
9596

97+
private disposeCollection = new DisposableCollection();
98+
9699
constructor(
97100
opts: IServerAppOpts & {
98101
injector: Injector;
@@ -124,8 +127,15 @@ export class ServerApp implements IServerApp {
124127
}
125128

126129
private registerEventListeners() {
127-
window.addEventListener('unload', () => {
130+
const handleUnload = () => {
128131
this.stopContribution();
132+
};
133+
window.addEventListener('unload', handleUnload);
134+
135+
this.disposeCollection.push({
136+
dispose: () => {
137+
window.removeEventListener('unload', handleUnload);
138+
},
129139
});
130140
}
131141

@@ -205,6 +215,10 @@ export class ServerApp implements IServerApp {
205215
bindModuleBackService(this.injector, this.modules);
206216
await this.startContribution();
207217
}
218+
219+
dispose() {
220+
this.disposeCollection.dispose();
221+
}
208222
}
209223

210224
export function bindModuleBackService(injector: Injector, modules: ModuleConstructor[]) {

0 commit comments

Comments
 (0)