@ives_xxz/framework 1.4.13 → 1.4.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FW.d.ts +54 -2
- package/entry/FWEntry.ts +6 -1
- package/manager/FWAssetManager.ts +40 -37
- package/manager/FWEngineManager.ts +2 -1
- package/manager/FWLayerManager.ts +248 -223
- package/manager/FWManager.ts +53 -3
- package/manager/FWPerformanceManager.ts +201 -0
- package/manager/FWPerformanceManager.ts.meta +10 -0
- package/package.json +1 -1
- package/service/FWService.ts +47 -0
- package/service/http/FWHttp.ts +42 -26
- package/utils/FWTask.ts +1 -1
package/FW.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ declare namespace FW {
|
|
|
35
35
|
taskMgr: TaskManager;
|
|
36
36
|
hotUpdateMgr: HotUpdateManager;
|
|
37
37
|
promiseMgr: PromiseManager;
|
|
38
|
+
performanceMgr: PerformanceManager;
|
|
38
39
|
scene: Scene;
|
|
39
40
|
bundleName: string;
|
|
40
41
|
getComponent<T>(serviceIdentifier: FW.ServiceIdentifier<T>): T;
|
|
@@ -49,6 +50,8 @@ declare namespace FW {
|
|
|
49
50
|
onDestroy(): void;
|
|
50
51
|
};
|
|
51
52
|
|
|
53
|
+
type Manager = {};
|
|
54
|
+
|
|
52
55
|
type PromiseManager = {
|
|
53
56
|
execute<T = any>(
|
|
54
57
|
executor: (
|
|
@@ -1611,6 +1614,12 @@ declare namespace FW {
|
|
|
1611
1614
|
setEffectsMute(mute: boolean): void;
|
|
1612
1615
|
};
|
|
1613
1616
|
|
|
1617
|
+
type PerformanceManager = {
|
|
1618
|
+
recordOperationMetric(manager: string, operation: string, duration: number): void;
|
|
1619
|
+
getManagerReport(manager: string): PerformanceReport;
|
|
1620
|
+
getAllReports(): Map<string, FW.PerformanceReport>;
|
|
1621
|
+
};
|
|
1622
|
+
|
|
1614
1623
|
type Object = {
|
|
1615
1624
|
/** 是否已经初始化 */
|
|
1616
1625
|
initialize: boolean;
|
|
@@ -1779,7 +1788,7 @@ declare namespace FW {
|
|
|
1779
1788
|
*/
|
|
1780
1789
|
type TaskFunction = () => TaskGenerator;
|
|
1781
1790
|
|
|
1782
|
-
type
|
|
1791
|
+
type TaskPerformanceReport = {
|
|
1783
1792
|
startTime: string;
|
|
1784
1793
|
endTime: string;
|
|
1785
1794
|
totalTasks: number;
|
|
@@ -1833,7 +1842,7 @@ declare namespace FW {
|
|
|
1833
1842
|
/**
|
|
1834
1843
|
* 获取任务性能报告
|
|
1835
1844
|
*/
|
|
1836
|
-
getPerformanceReport():
|
|
1845
|
+
getPerformanceReport(): TaskPerformanceReport;
|
|
1837
1846
|
};
|
|
1838
1847
|
|
|
1839
1848
|
type FrameDetail = {
|
|
@@ -1928,6 +1937,49 @@ declare namespace FW {
|
|
|
1928
1937
|
|
|
1929
1938
|
type PromiseStatus = 'pending' | 'fulfilled' | 'rejected' | 'cancelled';
|
|
1930
1939
|
|
|
1940
|
+
/**
|
|
1941
|
+
* 性能管理器配置
|
|
1942
|
+
*/
|
|
1943
|
+
type PerformanceManagerOptions = {
|
|
1944
|
+
/** 是否自动收集性能数据 */
|
|
1945
|
+
autoCollect?: boolean;
|
|
1946
|
+
/** 性能数据保留时间(毫秒) */
|
|
1947
|
+
dataRetentionTime?: number;
|
|
1948
|
+
/** 采样率(0-1) */
|
|
1949
|
+
samplingRate?: number;
|
|
1950
|
+
/** 性能警告阈值(毫秒) */
|
|
1951
|
+
warningThreshold?: number;
|
|
1952
|
+
};
|
|
1953
|
+
|
|
1954
|
+
/**
|
|
1955
|
+
* 性能统计报告
|
|
1956
|
+
*/
|
|
1957
|
+
type PerformanceReport = {
|
|
1958
|
+
manager: string;
|
|
1959
|
+
totalOperations: number;
|
|
1960
|
+
averageDuration: number;
|
|
1961
|
+
minDuration: number;
|
|
1962
|
+
maxDuration: number;
|
|
1963
|
+
recentMetrics: FWPerformanceMetric[];
|
|
1964
|
+
};
|
|
1965
|
+
|
|
1966
|
+
/**
|
|
1967
|
+
* 性能指标数据
|
|
1968
|
+
*/
|
|
1969
|
+
type PerformanceMetric = {
|
|
1970
|
+
manager: string;
|
|
1971
|
+
operation: string;
|
|
1972
|
+
duration: number;
|
|
1973
|
+
timestamp: number;
|
|
1974
|
+
};
|
|
1975
|
+
|
|
1976
|
+
type ManagerOptions = {
|
|
1977
|
+
/** 是否启用调试日志 */
|
|
1978
|
+
debug?: boolean;
|
|
1979
|
+
/** 管理器名称(默认使用类名) */
|
|
1980
|
+
name?: string;
|
|
1981
|
+
};
|
|
1982
|
+
|
|
1931
1983
|
declare function timeScale(scale: number);
|
|
1932
1984
|
declare let Entry: Entry;
|
|
1933
1985
|
}
|
package/entry/FWEntry.ts
CHANGED
|
@@ -19,6 +19,7 @@ import FWTaskManager from '../manager/FWTaskManager';
|
|
|
19
19
|
import FWEngineManager from '../manager/FWEngineManager';
|
|
20
20
|
import FWHotUpdateManager from '../manager/FWHotUpdateManager';
|
|
21
21
|
import FWPromiseManager from '../manager/FWPromiseManager';
|
|
22
|
+
import { FWPerformanceManager } from '../manager/FWPerformanceManager';
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* 入口脚本
|
|
@@ -89,6 +90,10 @@ export default class FWEntry implements FW.Entry {
|
|
|
89
90
|
* promise管理器
|
|
90
91
|
*/
|
|
91
92
|
promiseMgr: FW.PromiseManager;
|
|
93
|
+
/**
|
|
94
|
+
* 性能管理器
|
|
95
|
+
*/
|
|
96
|
+
performanceMgr: FW.PerformanceManager;
|
|
92
97
|
/**
|
|
93
98
|
* 当前Scene
|
|
94
99
|
*/
|
|
@@ -119,7 +124,7 @@ export default class FWEntry implements FW.Entry {
|
|
|
119
124
|
this.languageMgr = new FWLanguageManager();
|
|
120
125
|
this.hotUpdateMgr = new FWHotUpdateManager();
|
|
121
126
|
this.promiseMgr = new FWPromiseManager();
|
|
122
|
-
|
|
127
|
+
this.performanceMgr = new FWPerformanceManager();
|
|
123
128
|
this.resMgr.initialize();
|
|
124
129
|
this.layerMgr.initialize();
|
|
125
130
|
this.timeMgr.initialize();
|
|
@@ -131,43 +131,46 @@ export class FWAssetManager extends FWManager implements FW.AssetManager {
|
|
|
131
131
|
|
|
132
132
|
assetData.loaded = false;
|
|
133
133
|
|
|
134
|
-
return
|
|
135
|
-
(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
134
|
+
return await this.invoke(
|
|
135
|
+
FW.Entry.promiseMgr.execute(
|
|
136
|
+
(resolve, reject, signal) => {
|
|
137
|
+
const self = this;
|
|
138
|
+
|
|
139
|
+
bundle.load(
|
|
140
|
+
path,
|
|
141
|
+
type,
|
|
142
|
+
(finish: number, total: number, item: cc.AssetManager.RequestItem) => {
|
|
143
|
+
progress?.(finish, total, item);
|
|
144
|
+
},
|
|
145
|
+
(err: Error, asset: cc.Asset) => {
|
|
146
|
+
if (err || !asset) {
|
|
147
|
+
reject(err);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
assetData.loaded = true;
|
|
151
|
+
assetData.dependentBundle = bundleName;
|
|
152
|
+
assetData.uuid = asset['_uuid'];
|
|
153
|
+
assetData.autoRelease = autoRelease;
|
|
154
|
+
assetData.asset = asset;
|
|
155
|
+
assetData.user = assetProperty.user;
|
|
156
|
+
assetData.refCount = 1;
|
|
157
|
+
assetData.assetProperty = assetProperty;
|
|
158
|
+
|
|
159
|
+
self.assetsMap.set(key, assetData);
|
|
160
|
+
|
|
161
|
+
cb?.(assetData);
|
|
162
|
+
resolve(assetData);
|
|
163
|
+
},
|
|
164
|
+
);
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
retryCount: 3,
|
|
168
|
+
retryInterval: 1,
|
|
169
|
+
timeout: 10,
|
|
170
|
+
},
|
|
171
|
+
).promise,
|
|
172
|
+
`loadAssets -> ${assetProperty.path}`,
|
|
173
|
+
);
|
|
171
174
|
}
|
|
172
175
|
/**
|
|
173
176
|
* 加载文件夹
|
|
@@ -3,7 +3,8 @@ import FWLog from '../log/FWLog';
|
|
|
3
3
|
import { FWManager } from './FWManager';
|
|
4
4
|
|
|
5
5
|
export default class FWEngineManager extends FWManager implements FW.EngineManager {
|
|
6
|
-
debug: boolean =
|
|
6
|
+
debug: boolean = false;
|
|
7
|
+
|
|
7
8
|
initialize() {
|
|
8
9
|
this.registerCCCSystemEvent();
|
|
9
10
|
}
|
|
@@ -7,6 +7,218 @@ import { FWQueue } from '../utils/FWQueue';
|
|
|
7
7
|
|
|
8
8
|
const ADD_EXTERNAL_REFERENCE: string = 'addExternalReference';
|
|
9
9
|
|
|
10
|
+
export class FWLayerManager extends FWManager implements FW.LayerManager {
|
|
11
|
+
private resourceManager: FWLayerResourceManager;
|
|
12
|
+
private dataManager: FWLayerDataManager;
|
|
13
|
+
private createManager: FWLayerCreateManager;
|
|
14
|
+
private stackManager: FWLayerStackManager;
|
|
15
|
+
private stateManager: FWLayerStateManager;
|
|
16
|
+
private queueManager: FWLayerQueueManager;
|
|
17
|
+
private openManager: FWLayerOpenManager;
|
|
18
|
+
|
|
19
|
+
public initialize(): void {
|
|
20
|
+
this.resourceManager = new FWLayerResourceManager();
|
|
21
|
+
this.dataManager = new FWLayerDataManager();
|
|
22
|
+
this.createManager = new FWLayerCreateManager();
|
|
23
|
+
this.stackManager = new FWLayerStackManager();
|
|
24
|
+
this.stateManager = new FWLayerStateManager();
|
|
25
|
+
this.queueManager = new FWLayerQueueManager();
|
|
26
|
+
|
|
27
|
+
this.openManager = new FWLayerOpenManager(
|
|
28
|
+
this.dataManager,
|
|
29
|
+
this.resourceManager,
|
|
30
|
+
this.createManager,
|
|
31
|
+
this.stackManager,
|
|
32
|
+
this.queueManager,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 异步打开Layer
|
|
38
|
+
*/
|
|
39
|
+
async openAsync<Ctr extends FW.LayerController = FW.LayerController>(
|
|
40
|
+
data: FW.LayerOpenArgs,
|
|
41
|
+
): Promise<Ctr> {
|
|
42
|
+
return this.openManager.openLayerAsync(data) as Promise<Ctr>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 同步打开
|
|
47
|
+
*/
|
|
48
|
+
openSync<Ctr extends FW.LayerController = FW.LayerController>(data: FW.LayerOpenArgs): Ctr {
|
|
49
|
+
return this.openManager.openLayerSync(data) as unknown as Ctr;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 显示layer并恢复所有节点事件
|
|
54
|
+
*/
|
|
55
|
+
displayLayer<Ctr extends FW.LayerController = FW.LayerController>(ctr: Ctr): Ctr {
|
|
56
|
+
const layerData = ctr.layerData;
|
|
57
|
+
|
|
58
|
+
if (!this.dataManager.getLayerMap().has(ctr.layerData.controllerConstructor)) {
|
|
59
|
+
FWLog.warn(`display layer failed,layer name : ${layerData.layerName}`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
/** 非常驻layer不允许操作透明度显示 */
|
|
63
|
+
if (ctr.layerType != FWSystemDefine.FWLayerType.PERMANENT) return;
|
|
64
|
+
|
|
65
|
+
const node = ctr.layer.node;
|
|
66
|
+
node.opacity = 255;
|
|
67
|
+
node.resumeSystemEvents(true);
|
|
68
|
+
|
|
69
|
+
FW.Entry.evtMgr.targetResume(ctr);
|
|
70
|
+
FW.Entry.timeMgr.resumeSchedule(ctr);
|
|
71
|
+
|
|
72
|
+
return ctr;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 隐藏layer并隐藏所有节点事件
|
|
77
|
+
*/
|
|
78
|
+
hideLayer<Ctr extends FW.LayerController = FW.LayerController>(ctr: Ctr): Ctr {
|
|
79
|
+
const layerData = ctr.layerData;
|
|
80
|
+
if (!this.dataManager.getLayerMap().has(ctr.layerData.controllerConstructor)) {
|
|
81
|
+
FWLog.warn(`hide layer failed,layer name : ${layerData.layerName}`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** 非常驻layer不允许操作透明度 */
|
|
86
|
+
if (ctr.layerType != FWSystemDefine.FWLayerType.PERMANENT) return;
|
|
87
|
+
|
|
88
|
+
const node = ctr.layer.node;
|
|
89
|
+
node.opacity = 0;
|
|
90
|
+
node.pauseSystemEvents(true);
|
|
91
|
+
FW.Entry.evtMgr.targetPause(ctr);
|
|
92
|
+
FW.Entry.timeMgr.pauseSchedule(ctr);
|
|
93
|
+
|
|
94
|
+
return ctr;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 通过layer名字关闭
|
|
99
|
+
*/
|
|
100
|
+
closeFromLayerName(name: string | string[]): void {
|
|
101
|
+
this.dataManager.getLayerMap().forEach((v) => {
|
|
102
|
+
if (Array.isArray(name)) {
|
|
103
|
+
name.forEach((n) => {
|
|
104
|
+
if (n === v.layerName) {
|
|
105
|
+
this.close(v.controller);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
} else {
|
|
109
|
+
if (v.layerName == name) {
|
|
110
|
+
this.close(v.controller);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 从栈关闭
|
|
118
|
+
*/
|
|
119
|
+
closeFromStack(count?: number) {
|
|
120
|
+
count = count ? count : 1;
|
|
121
|
+
for (let i = 0; i < count; i++) {
|
|
122
|
+
let layerData = this.stackManager.pop();
|
|
123
|
+
let ctr = layerData.controller;
|
|
124
|
+
if (!this.dataManager.getLayerMap().has(layerData.controllerConstructor)) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (cc.isValid(ctr.layer?.node)) {
|
|
128
|
+
ctr.layer.destroy?.();
|
|
129
|
+
if (ctr.autoRelease) {
|
|
130
|
+
FW.Entry.resMgr.releaseAsset(ctr.layerData.layerAssetProperty);
|
|
131
|
+
}
|
|
132
|
+
this.dataManager.notifyExternalRefUpdates(ctr.layerData);
|
|
133
|
+
}
|
|
134
|
+
this.dataManager.removeFromMap(layerData.controllerConstructor);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* 移除指定Layer所有子Layer
|
|
139
|
+
* @param layer
|
|
140
|
+
* @returns
|
|
141
|
+
*/
|
|
142
|
+
async removeAllChildren(node: cc.Node) {
|
|
143
|
+
if (!cc.isValid(node)) return;
|
|
144
|
+
const layers = node.getComponentsInChildren(FWLayer);
|
|
145
|
+
layers.forEach((v) => {
|
|
146
|
+
if (cc.isValid(v?.node)) {
|
|
147
|
+
v?.ctr?.close();
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 关闭layer
|
|
154
|
+
*/
|
|
155
|
+
async close<Ctr extends FW.LayerController = FW.LayerController>(
|
|
156
|
+
ctr: Ctr,
|
|
157
|
+
): Promise<FW.LayerController> {
|
|
158
|
+
if (!ctr) return;
|
|
159
|
+
|
|
160
|
+
let layerData = ctr.layerData;
|
|
161
|
+
|
|
162
|
+
if (cc.isValid(ctr.layer?.node)) {
|
|
163
|
+
await ctr.onClose?.();
|
|
164
|
+
ctr.destroy?.();
|
|
165
|
+
if (ctr.autoRelease) {
|
|
166
|
+
FW.Entry.resMgr.releaseAsset(ctr.layerData.layerAssetProperty);
|
|
167
|
+
}
|
|
168
|
+
this.dataManager.notifyExternalRefUpdates(ctr.layerData);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
this.dataManager.removeFromMap(layerData.controllerConstructor);
|
|
172
|
+
this.dataManager.removeFromRegistry(ctr.layerData.controllerConstructor);
|
|
173
|
+
|
|
174
|
+
const index = this.stackManager.getStack().findIndex((v) => {
|
|
175
|
+
v.controller == ctr;
|
|
176
|
+
});
|
|
177
|
+
if (index > -1) {
|
|
178
|
+
this.stackManager.getStack().splice(index, 1);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** 如果队列中还有等待打开的layer */
|
|
182
|
+
if (!this.queueManager.isEmpty()) {
|
|
183
|
+
const nextLayerData = this.queueManager.getNextLayer();
|
|
184
|
+
/** 先尝试同步打开 */
|
|
185
|
+
const nextLayer = this.openSync({
|
|
186
|
+
parent: nextLayerData.layerParent,
|
|
187
|
+
position: nextLayerData.layerPosition,
|
|
188
|
+
type: nextLayerData.controllerConstructor,
|
|
189
|
+
});
|
|
190
|
+
/** 如果同步打开失败,再次尝试异步打开(可能由于资源所在bundle并未提前加载) */
|
|
191
|
+
if (!nextLayer) {
|
|
192
|
+
return this.openAsync({
|
|
193
|
+
parent: nextLayerData.layerParent,
|
|
194
|
+
position: nextLayerData.layerPosition,
|
|
195
|
+
type: nextLayerData.controllerConstructor,
|
|
196
|
+
});
|
|
197
|
+
} else {
|
|
198
|
+
return nextLayer;
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
getLayerMap(): Map<new () => FW.LayerController, FWLayerData> {
|
|
206
|
+
return this.dataManager.getLayerMap();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public clear() {
|
|
210
|
+
this.dataManager.getLayerMap().forEach((v) => this.close(v.controller));
|
|
211
|
+
this.queueManager.clear();
|
|
212
|
+
this.stackManager.clear();
|
|
213
|
+
this.stateManager.clear();
|
|
214
|
+
this.dataManager.clear();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
public onDestroy(): void {
|
|
218
|
+
this.clear();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
10
222
|
export class FWLayerData<T extends FW.LayerController = FW.LayerController>
|
|
11
223
|
implements FW.LayerData
|
|
12
224
|
{
|
|
@@ -240,41 +452,66 @@ class FWLayerOpenManager {
|
|
|
240
452
|
/**
|
|
241
453
|
* 统一的Layer打开方法
|
|
242
454
|
*/
|
|
243
|
-
async
|
|
455
|
+
async openLayerAsync<Ctr extends FW.LayerController = FW.LayerController>(
|
|
244
456
|
data: FW.LayerOpenArgs,
|
|
245
|
-
isAsync: boolean,
|
|
246
457
|
): Promise<Ctr> {
|
|
247
458
|
if (!this.validateOpenData(data)) {
|
|
248
|
-
return
|
|
459
|
+
return undefined;
|
|
249
460
|
}
|
|
250
461
|
|
|
251
462
|
const existingLayer = this.dataManager.getExistingLayer(data.type);
|
|
252
463
|
if (existingLayer) {
|
|
253
|
-
return
|
|
464
|
+
return existingLayer as Ctr;
|
|
254
465
|
}
|
|
255
466
|
|
|
256
467
|
const layerData = this.dataManager.createLayerData(data.type);
|
|
257
468
|
|
|
258
469
|
if (!layerData) {
|
|
259
|
-
return
|
|
470
|
+
return undefined;
|
|
260
471
|
}
|
|
261
472
|
|
|
262
473
|
if (this.dataManager.addRegistry(data.type)) {
|
|
263
474
|
const proxy = this.dataManager.getExistingProxy(data.type);
|
|
264
|
-
return
|
|
475
|
+
return proxy as Ctr;
|
|
265
476
|
}
|
|
266
477
|
|
|
267
478
|
if (this.queueManager.handlePopupQueue(layerData, this.dataManager.getLayerMap())) {
|
|
268
|
-
return
|
|
479
|
+
return undefined;
|
|
269
480
|
}
|
|
270
481
|
|
|
271
482
|
this.dataManager.addLayerData(data.type, layerData);
|
|
272
483
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
484
|
+
return this.asyncGenerationLayer(layerData, data);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
openLayerSync<Ctr extends FW.LayerController = FW.LayerController>(data: FW.LayerOpenArgs): Ctr {
|
|
488
|
+
if (!this.validateOpenData(data)) {
|
|
489
|
+
return undefined;
|
|
277
490
|
}
|
|
491
|
+
|
|
492
|
+
const existingLayer = this.dataManager.getExistingLayer(data.type);
|
|
493
|
+
if (existingLayer) {
|
|
494
|
+
return existingLayer as Ctr;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const layerData = this.dataManager.createLayerData(data.type);
|
|
498
|
+
|
|
499
|
+
if (!layerData) {
|
|
500
|
+
return undefined;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (this.dataManager.addRegistry(data.type)) {
|
|
504
|
+
const proxy = this.dataManager.getExistingProxy(data.type);
|
|
505
|
+
return proxy as Ctr;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (this.queueManager.handlePopupQueue(layerData, this.dataManager.getLayerMap())) {
|
|
509
|
+
return undefined;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
this.dataManager.addLayerData(data.type, layerData);
|
|
513
|
+
|
|
514
|
+
return this.syncGenerationLayer(layerData, data);
|
|
278
515
|
}
|
|
279
516
|
|
|
280
517
|
/**
|
|
@@ -551,215 +788,3 @@ class FWLayerLifecycleManager {
|
|
|
551
788
|
};
|
|
552
789
|
}
|
|
553
790
|
}
|
|
554
|
-
|
|
555
|
-
export class FWLayerManager extends FWManager implements FW.LayerManager {
|
|
556
|
-
private resourceManager: FWLayerResourceManager;
|
|
557
|
-
private dataManager: FWLayerDataManager;
|
|
558
|
-
private createManager: FWLayerCreateManager;
|
|
559
|
-
private stackManager: FWLayerStackManager;
|
|
560
|
-
private stateManager: FWLayerStateManager;
|
|
561
|
-
private queueManager: FWLayerQueueManager;
|
|
562
|
-
private openManager: FWLayerOpenManager;
|
|
563
|
-
|
|
564
|
-
public initialize(): void {
|
|
565
|
-
this.resourceManager = new FWLayerResourceManager();
|
|
566
|
-
this.dataManager = new FWLayerDataManager();
|
|
567
|
-
this.createManager = new FWLayerCreateManager();
|
|
568
|
-
this.stackManager = new FWLayerStackManager();
|
|
569
|
-
this.stateManager = new FWLayerStateManager();
|
|
570
|
-
this.queueManager = new FWLayerQueueManager();
|
|
571
|
-
|
|
572
|
-
this.openManager = new FWLayerOpenManager(
|
|
573
|
-
this.dataManager,
|
|
574
|
-
this.resourceManager,
|
|
575
|
-
this.createManager,
|
|
576
|
-
this.stackManager,
|
|
577
|
-
this.queueManager,
|
|
578
|
-
);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
/**
|
|
582
|
-
* 异步打开Layer
|
|
583
|
-
*/
|
|
584
|
-
async openAsync<Ctr extends FW.LayerController = FW.LayerController>(
|
|
585
|
-
data: FW.LayerOpenArgs,
|
|
586
|
-
): Promise<Ctr> {
|
|
587
|
-
return this.openManager.openLayer(data, true) as Promise<Ctr>;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
* 同步打开
|
|
592
|
-
*/
|
|
593
|
-
openSync<Ctr extends FW.LayerController = FW.LayerController>(data: FW.LayerOpenArgs): Ctr {
|
|
594
|
-
return this.openManager.openLayer(data, false) as unknown as Ctr;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
/**
|
|
598
|
-
* 显示layer并恢复所有节点事件
|
|
599
|
-
*/
|
|
600
|
-
displayLayer<Ctr extends FW.LayerController = FW.LayerController>(ctr: Ctr): Ctr {
|
|
601
|
-
const layerData = ctr.layerData;
|
|
602
|
-
|
|
603
|
-
if (!this.dataManager.getLayerMap().has(ctr.layerData.controllerConstructor)) {
|
|
604
|
-
FWLog.warn(`display layer failed,layer name : ${layerData.layerName}`);
|
|
605
|
-
return;
|
|
606
|
-
}
|
|
607
|
-
/** 非常驻layer不允许操作透明度显示 */
|
|
608
|
-
if (ctr.layerType != FWSystemDefine.FWLayerType.PERMANENT) return;
|
|
609
|
-
|
|
610
|
-
const node = ctr.layer.node;
|
|
611
|
-
node.opacity = 255;
|
|
612
|
-
node.resumeSystemEvents(true);
|
|
613
|
-
|
|
614
|
-
FW.Entry.evtMgr.targetResume(ctr);
|
|
615
|
-
FW.Entry.timeMgr.resumeSchedule(ctr);
|
|
616
|
-
|
|
617
|
-
return ctr;
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
/**
|
|
621
|
-
* 隐藏layer并隐藏所有节点事件
|
|
622
|
-
*/
|
|
623
|
-
hideLayer<Ctr extends FW.LayerController = FW.LayerController>(ctr: Ctr): Ctr {
|
|
624
|
-
const layerData = ctr.layerData;
|
|
625
|
-
if (!this.dataManager.getLayerMap().has(ctr.layerData.controllerConstructor)) {
|
|
626
|
-
FWLog.warn(`hide layer failed,layer name : ${layerData.layerName}`);
|
|
627
|
-
return;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
/** 非常驻layer不允许操作透明度 */
|
|
631
|
-
if (ctr.layerType != FWSystemDefine.FWLayerType.PERMANENT) return;
|
|
632
|
-
|
|
633
|
-
const node = ctr.layer.node;
|
|
634
|
-
node.opacity = 0;
|
|
635
|
-
node.pauseSystemEvents(true);
|
|
636
|
-
FW.Entry.evtMgr.targetPause(ctr);
|
|
637
|
-
FW.Entry.timeMgr.pauseSchedule(ctr);
|
|
638
|
-
|
|
639
|
-
return ctr;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
/**
|
|
643
|
-
* 通过layer名字关闭
|
|
644
|
-
*/
|
|
645
|
-
closeFromLayerName(name: string | string[]): void {
|
|
646
|
-
this.dataManager.getLayerMap().forEach((v) => {
|
|
647
|
-
if (Array.isArray(name)) {
|
|
648
|
-
name.forEach((n) => {
|
|
649
|
-
if (n === v.layerName) {
|
|
650
|
-
this.close(v.controller);
|
|
651
|
-
}
|
|
652
|
-
});
|
|
653
|
-
} else {
|
|
654
|
-
if (v.layerName == name) {
|
|
655
|
-
this.close(v.controller);
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
});
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
/**
|
|
662
|
-
* 从栈关闭
|
|
663
|
-
*/
|
|
664
|
-
closeFromStack(count?: number) {
|
|
665
|
-
count = count ? count : 1;
|
|
666
|
-
for (let i = 0; i < count; i++) {
|
|
667
|
-
let layerData = this.stackManager.pop();
|
|
668
|
-
let ctr = layerData.controller;
|
|
669
|
-
if (!this.dataManager.getLayerMap().has(layerData.controllerConstructor)) {
|
|
670
|
-
return;
|
|
671
|
-
}
|
|
672
|
-
if (cc.isValid(ctr.layer?.node)) {
|
|
673
|
-
ctr.layer.destroy?.();
|
|
674
|
-
if (ctr.autoRelease) {
|
|
675
|
-
FW.Entry.resMgr.releaseAsset(ctr.layerData.layerAssetProperty);
|
|
676
|
-
}
|
|
677
|
-
this.dataManager.notifyExternalRefUpdates(ctr.layerData);
|
|
678
|
-
}
|
|
679
|
-
this.dataManager.removeFromMap(layerData.controllerConstructor);
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
/**
|
|
683
|
-
* 移除指定Layer所有子Layer
|
|
684
|
-
* @param layer
|
|
685
|
-
* @returns
|
|
686
|
-
*/
|
|
687
|
-
async removeAllChildren(node: cc.Node) {
|
|
688
|
-
if (!cc.isValid(node)) return;
|
|
689
|
-
const layers = node.getComponentsInChildren(FWLayer);
|
|
690
|
-
layers.forEach((v) => {
|
|
691
|
-
if (cc.isValid(v?.node)) {
|
|
692
|
-
v?.ctr?.close();
|
|
693
|
-
}
|
|
694
|
-
});
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
/**
|
|
698
|
-
* 关闭layer
|
|
699
|
-
*/
|
|
700
|
-
async close<Ctr extends FW.LayerController = FW.LayerController>(
|
|
701
|
-
ctr: Ctr,
|
|
702
|
-
): Promise<FW.LayerController> {
|
|
703
|
-
if (!ctr) return;
|
|
704
|
-
|
|
705
|
-
let layerData = ctr.layerData;
|
|
706
|
-
|
|
707
|
-
if (cc.isValid(ctr.layer?.node)) {
|
|
708
|
-
await ctr.onClose?.();
|
|
709
|
-
ctr.destroy?.();
|
|
710
|
-
if (ctr.autoRelease) {
|
|
711
|
-
FW.Entry.resMgr.releaseAsset(ctr.layerData.layerAssetProperty);
|
|
712
|
-
}
|
|
713
|
-
this.dataManager.notifyExternalRefUpdates(ctr.layerData);
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
this.dataManager.removeFromMap(layerData.controllerConstructor);
|
|
717
|
-
this.dataManager.removeFromRegistry(ctr.layerData.controllerConstructor);
|
|
718
|
-
|
|
719
|
-
const index = this.stackManager.getStack().findIndex((v) => {
|
|
720
|
-
v.controller == ctr;
|
|
721
|
-
});
|
|
722
|
-
if (index > -1) {
|
|
723
|
-
this.stackManager.getStack().splice(index, 1);
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
/** 如果队列中还有等待打开的layer */
|
|
727
|
-
if (!this.queueManager.isEmpty()) {
|
|
728
|
-
const nextLayerData = this.queueManager.getNextLayer();
|
|
729
|
-
/** 先尝试同步打开 */
|
|
730
|
-
const nextLayer = this.openSync({
|
|
731
|
-
parent: nextLayerData.layerParent,
|
|
732
|
-
position: nextLayerData.layerPosition,
|
|
733
|
-
type: nextLayerData.controllerConstructor,
|
|
734
|
-
});
|
|
735
|
-
/** 如果同步打开失败,再次尝试异步打开(可能由于资源所在bundle并未提前加载) */
|
|
736
|
-
if (!nextLayer) {
|
|
737
|
-
return this.openAsync({
|
|
738
|
-
parent: nextLayerData.layerParent,
|
|
739
|
-
position: nextLayerData.layerPosition,
|
|
740
|
-
type: nextLayerData.controllerConstructor,
|
|
741
|
-
});
|
|
742
|
-
} else {
|
|
743
|
-
return nextLayer;
|
|
744
|
-
}
|
|
745
|
-
} else {
|
|
746
|
-
return undefined;
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
getLayerMap(): Map<new () => FW.LayerController, FWLayerData> {
|
|
751
|
-
return this.dataManager.getLayerMap();
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
public clear() {
|
|
755
|
-
this.queueManager.clear();
|
|
756
|
-
this.stackManager.clear();
|
|
757
|
-
this.stateManager.clear();
|
|
758
|
-
this.dataManager.clear();
|
|
759
|
-
this.dataManager.getLayerMap().forEach((v) => this.close(v.controller));
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
public onDestroy(): void {
|
|
763
|
-
this.clear();
|
|
764
|
-
}
|
|
765
|
-
}
|
package/manager/FWManager.ts
CHANGED
|
@@ -1,8 +1,58 @@
|
|
|
1
|
-
|
|
1
|
+
import FWLog from '../log/FWLog';
|
|
2
|
+
|
|
3
|
+
export abstract class FWManager implements FW.Manager {
|
|
2
4
|
public readonly entry: FW.Entry = FW.Entry;
|
|
5
|
+
public readonly managerName: string = this.constructor.name;
|
|
6
|
+
|
|
7
|
+
public abstract initialize(): void;
|
|
8
|
+
public abstract onDestroy(): void;
|
|
9
|
+
|
|
3
10
|
constructor() {
|
|
4
11
|
this.initialize();
|
|
5
12
|
}
|
|
6
|
-
|
|
7
|
-
|
|
13
|
+
|
|
14
|
+
protected async invoke<T>(operation: Promise<T>, operationName: string = 'unknown'): Promise<T> {
|
|
15
|
+
const startTime = this.getCurrentTime();
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const result = await operation;
|
|
19
|
+
const duration = this.getCurrentTime() - startTime;
|
|
20
|
+
|
|
21
|
+
this.recordPerformanceMetric(operationName, duration);
|
|
22
|
+
return result;
|
|
23
|
+
} catch (error) {
|
|
24
|
+
this.handleError(operationName, error);
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private recordPerformanceMetric(operationName: string, duration: number): void {
|
|
30
|
+
if (FW.Entry.performanceMgr) {
|
|
31
|
+
FW.Entry.performanceMgr.recordOperationMetric(this.managerName, operationName, duration);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (duration > 1000) {
|
|
35
|
+
FWLog.warn(`Operation ${operationName} took ${duration}ms`);
|
|
36
|
+
} else if (FW.Entry.engineMgr.debug) {
|
|
37
|
+
FWLog.debug(`Operation ${operationName} took ${duration}ms`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected handleError(operation: string, error: any): void {
|
|
42
|
+
const errorInfo = {
|
|
43
|
+
manager: this.managerName,
|
|
44
|
+
operation,
|
|
45
|
+
error: error?.message || error,
|
|
46
|
+
stack: error?.stack,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
FWLog.error(`Manager error in ${this.managerName}.${operation}:`, errorInfo);
|
|
50
|
+
|
|
51
|
+
if (CC_DEBUG && FW.Entry.engineMgr.debug) {
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
protected getCurrentTime(): number {
|
|
56
|
+
return Date.now();
|
|
57
|
+
}
|
|
8
58
|
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// FWPerformanceManager.ts
|
|
2
|
+
|
|
3
|
+
import FWLog from '../log/FWLog';
|
|
4
|
+
import { FWManager } from './FWManager';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 性能管理器
|
|
8
|
+
*/
|
|
9
|
+
export class FWPerformanceManager extends FWManager implements FW.PerformanceManager {
|
|
10
|
+
private metrics: FW.PerformanceMetric[] = [];
|
|
11
|
+
private managerStats: Map<
|
|
12
|
+
string,
|
|
13
|
+
{
|
|
14
|
+
totalDuration: number;
|
|
15
|
+
operationCount: number;
|
|
16
|
+
minDuration: number;
|
|
17
|
+
maxDuration: number;
|
|
18
|
+
}
|
|
19
|
+
> = new Map();
|
|
20
|
+
|
|
21
|
+
private performanceOptions: FW.PerformanceManagerOptions;
|
|
22
|
+
|
|
23
|
+
public async initialize(): Promise<void> {
|
|
24
|
+
this.performanceOptions = {
|
|
25
|
+
autoCollect: true,
|
|
26
|
+
dataRetentionTime: 5 * 60 * 1000,
|
|
27
|
+
samplingRate: 1.0,
|
|
28
|
+
warningThreshold: 1000,
|
|
29
|
+
};
|
|
30
|
+
if (this.performanceOptions.autoCollect) {
|
|
31
|
+
this.startAutoCleanup();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public onDestroy(): void {
|
|
36
|
+
this.metrics = [];
|
|
37
|
+
this.managerStats.clear();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
protected onCleanup(): void {}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 记录操作性能指标
|
|
44
|
+
*/
|
|
45
|
+
public recordOperationMetric(manager: string, operation: string, duration: number): void {
|
|
46
|
+
if (Math.random() > this.performanceOptions.samplingRate!) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const metric: FW.PerformanceMetric = {
|
|
50
|
+
manager,
|
|
51
|
+
operation,
|
|
52
|
+
duration,
|
|
53
|
+
timestamp: Date.now(),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
this.metrics.push(metric);
|
|
57
|
+
this.updateManagerStats(manager, duration);
|
|
58
|
+
|
|
59
|
+
if (duration > this.performanceOptions.warningThreshold!) {
|
|
60
|
+
FWLog.warn(`Performance warning: ${manager}.${operation} took ${duration}ms`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 获取指定管理器的性能报告
|
|
66
|
+
*/
|
|
67
|
+
public getManagerReport(manager: string): FW.PerformanceReport | null {
|
|
68
|
+
const stats = this.managerStats.get(manager);
|
|
69
|
+
if (!stats) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const recentMetrics = this.metrics.filter((m) => m.manager === manager).slice(-500);
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
manager,
|
|
77
|
+
totalOperations: stats.operationCount,
|
|
78
|
+
averageDuration: stats.totalDuration / stats.operationCount,
|
|
79
|
+
minDuration: stats.minDuration,
|
|
80
|
+
maxDuration: stats.maxDuration,
|
|
81
|
+
recentMetrics,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 获取所有管理器的性能报告
|
|
87
|
+
*/
|
|
88
|
+
public getAllReports(): Map<string, FW.PerformanceReport> {
|
|
89
|
+
const reports = new Map<string, FW.PerformanceReport>();
|
|
90
|
+
|
|
91
|
+
this.managerStats.forEach((stats, manager) => {
|
|
92
|
+
const recentMetrics = this.metrics.filter((m) => m.manager === manager).slice(-500);
|
|
93
|
+
reports.set(manager, {
|
|
94
|
+
manager,
|
|
95
|
+
totalOperations: stats.operationCount,
|
|
96
|
+
averageDuration: stats.totalDuration / stats.operationCount,
|
|
97
|
+
minDuration: stats.minDuration,
|
|
98
|
+
maxDuration: stats.maxDuration,
|
|
99
|
+
recentMetrics,
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return reports;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* 获取性能摘要
|
|
108
|
+
*/
|
|
109
|
+
public getPerformanceSummary(): {
|
|
110
|
+
totalOperations: number;
|
|
111
|
+
averageOperationTime: number;
|
|
112
|
+
slowestManager: string;
|
|
113
|
+
mostActiveManager: string;
|
|
114
|
+
} {
|
|
115
|
+
let totalOperations = 0;
|
|
116
|
+
let totalDuration = 0;
|
|
117
|
+
let slowestManager = '';
|
|
118
|
+
let maxAvgDuration = 0;
|
|
119
|
+
let mostActiveManager = '';
|
|
120
|
+
let maxOperations = 0;
|
|
121
|
+
|
|
122
|
+
this.managerStats.forEach((stats, manager) => {
|
|
123
|
+
totalOperations += stats.operationCount;
|
|
124
|
+
totalDuration += stats.totalDuration;
|
|
125
|
+
|
|
126
|
+
const avgDuration = stats.totalDuration / stats.operationCount;
|
|
127
|
+
if (avgDuration > maxAvgDuration) {
|
|
128
|
+
maxAvgDuration = avgDuration;
|
|
129
|
+
slowestManager = manager;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (stats.operationCount > maxOperations) {
|
|
133
|
+
maxOperations = stats.operationCount;
|
|
134
|
+
mostActiveManager = manager;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
totalOperations,
|
|
140
|
+
averageOperationTime: totalOperations > 0 ? totalDuration / totalOperations : 0,
|
|
141
|
+
slowestManager,
|
|
142
|
+
mostActiveManager,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* 清理数据
|
|
148
|
+
*/
|
|
149
|
+
public clearPerformanceData(
|
|
150
|
+
retentionTime: number = this.performanceOptions.dataRetentionTime!,
|
|
151
|
+
): number {
|
|
152
|
+
const cutoffTime = Date.now() - retentionTime;
|
|
153
|
+
const initialLength = this.metrics.length;
|
|
154
|
+
|
|
155
|
+
this.metrics = this.metrics.filter((metric) => metric.timestamp > cutoffTime);
|
|
156
|
+
|
|
157
|
+
const removedCount = initialLength - this.metrics.length;
|
|
158
|
+
if (removedCount > 0) {
|
|
159
|
+
FWLog.debug(`Cleaned up ${removedCount} old performance records`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return removedCount;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* 重置所有性能数据
|
|
167
|
+
*/
|
|
168
|
+
public resetAllData(): void {
|
|
169
|
+
this.metrics = [];
|
|
170
|
+
this.managerStats.clear();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* 更新管理器统计信息
|
|
175
|
+
*/
|
|
176
|
+
private updateManagerStats(manager: string, duration: number): void {
|
|
177
|
+
if (!this.managerStats.has(manager)) {
|
|
178
|
+
this.managerStats.set(manager, {
|
|
179
|
+
totalDuration: 0,
|
|
180
|
+
operationCount: 0,
|
|
181
|
+
minDuration: Infinity,
|
|
182
|
+
maxDuration: -Infinity,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const stats = this.managerStats.get(manager)!;
|
|
187
|
+
stats.totalDuration += duration;
|
|
188
|
+
stats.operationCount++;
|
|
189
|
+
stats.minDuration = Math.min(stats.minDuration, duration);
|
|
190
|
+
stats.maxDuration = Math.max(stats.maxDuration, duration);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 启动自动清理任务
|
|
195
|
+
*/
|
|
196
|
+
private startAutoCleanup(): void {
|
|
197
|
+
FW.Entry.timeMgr.schedule(() => {
|
|
198
|
+
this.clearPerformanceData();
|
|
199
|
+
}, 300);
|
|
200
|
+
}
|
|
201
|
+
}
|
package/package.json
CHANGED
package/service/FWService.ts
CHANGED
|
@@ -1,7 +1,54 @@
|
|
|
1
|
+
import FWLog from '../log/FWLog';
|
|
2
|
+
|
|
1
3
|
export default abstract class FWService {
|
|
2
4
|
constructor() {
|
|
3
5
|
this.initialize();
|
|
4
6
|
}
|
|
5
7
|
public abstract initialize(): void;
|
|
6
8
|
public abstract destroy(): void;
|
|
9
|
+
public abstract readonly serviceName: string;
|
|
10
|
+
|
|
11
|
+
protected async invoke<T>(operation: Promise<T>, operationName: string = 'unknown'): Promise<T> {
|
|
12
|
+
const startTime = this.getCurrentTime();
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const result = await operation;
|
|
16
|
+
const duration = this.getCurrentTime() - startTime;
|
|
17
|
+
|
|
18
|
+
this.recordPerformanceMetric(operationName, duration);
|
|
19
|
+
return result;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
this.handleError(operationName, error);
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private recordPerformanceMetric(operationName: string, duration: number): void {
|
|
27
|
+
if (FW.Entry.performanceMgr) {
|
|
28
|
+
FW.Entry.performanceMgr.recordOperationMetric(this.serviceName, operationName, duration);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (FW.Entry.engineMgr.debug) {
|
|
32
|
+
const log = duration > 1000 ? FWLog.warn : FWLog.debug;
|
|
33
|
+
log(`Operation ${operationName} took ${duration}ms`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
protected getCurrentTime(): number {
|
|
38
|
+
return Date.now();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected handleError(operation: string, error: any): void {
|
|
42
|
+
const errorInfo = {
|
|
43
|
+
manager: this.serviceName,
|
|
44
|
+
operation,
|
|
45
|
+
error: error?.message || error,
|
|
46
|
+
stack: error?.stack,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
FWLog.error(`Manager error in ${this.serviceName}.${operation}:`, errorInfo);
|
|
50
|
+
|
|
51
|
+
if (FW.Entry.engineMgr.debug) {
|
|
52
|
+
}
|
|
53
|
+
}
|
|
7
54
|
}
|
package/service/http/FWHttp.ts
CHANGED
|
@@ -3,6 +3,7 @@ import FWLog from '../../log/FWLog';
|
|
|
3
3
|
import FWService from '../FWService';
|
|
4
4
|
|
|
5
5
|
export default class FWHttp extends FWService {
|
|
6
|
+
public serviceName: string = 'HTTP';
|
|
6
7
|
public initialize(): void {}
|
|
7
8
|
public destroy(): void {}
|
|
8
9
|
|
|
@@ -10,47 +11,62 @@ export default class FWHttp extends FWService {
|
|
|
10
11
|
url: string,
|
|
11
12
|
params?: string,
|
|
12
13
|
cb?: (response: string) => void,
|
|
14
|
+
tag?: string,
|
|
13
15
|
): Promise<string> {
|
|
14
|
-
return this.dataProcessing(url, params, cb, FWSystemDefine.FWHttpRequestType.GET);
|
|
16
|
+
return this.dataProcessing(url, params, cb, tag, FWSystemDefine.FWHttpRequestType.GET);
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
protected async postMessage(
|
|
18
20
|
url: string,
|
|
19
21
|
params?: string,
|
|
20
22
|
cb?: (response: string) => void,
|
|
23
|
+
tag?: string,
|
|
21
24
|
): Promise<string> {
|
|
22
|
-
return this.dataProcessing(url, params, cb, FWSystemDefine.FWHttpRequestType.POST);
|
|
25
|
+
return this.dataProcessing(url, params, cb, tag, FWSystemDefine.FWHttpRequestType.POST);
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
private dataProcessing(
|
|
28
|
+
private async dataProcessing(
|
|
26
29
|
url: string,
|
|
27
30
|
params: string,
|
|
28
31
|
cb: (response: any) => void,
|
|
32
|
+
tag: string,
|
|
29
33
|
type: FWSystemDefine.FWHttpRequestType,
|
|
30
34
|
): Promise<string> {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
35
|
+
let xhr: XMLHttpRequest;
|
|
36
|
+
return await this.invoke(
|
|
37
|
+
FW.Entry.promiseMgr.execute<string>(
|
|
38
|
+
(resolve, reject) => {
|
|
39
|
+
xhr = new XMLHttpRequest();
|
|
40
|
+
xhr.onreadystatechange = () => {
|
|
41
|
+
if (xhr.readyState == 4 && xhr.status === 200) {
|
|
42
|
+
cb?.(xhr.response);
|
|
43
|
+
resolve(xhr.response);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
xhr.onerror = (err: any) => {
|
|
48
|
+
FWLog.error(err);
|
|
49
|
+
this.onError(err);
|
|
50
|
+
reject(`http request error:${err}`);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
xhr.ontimeout = () => {
|
|
54
|
+
this.onTimeout();
|
|
55
|
+
reject(`http request timeout!`);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
xhr.open(type, url, true);
|
|
59
|
+
xhr.send(params);
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
retryCount: 3,
|
|
63
|
+
retryCondition(error, retryCount) {
|
|
64
|
+
return xhr.readyState != 4 || (xhr.status !== 200 && retryCount < 3);
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
).promise,
|
|
68
|
+
tag ? `http request ->${tag}` : '',
|
|
69
|
+
);
|
|
54
70
|
}
|
|
55
71
|
|
|
56
72
|
onError?(err: any);
|
package/utils/FWTask.ts
CHANGED
|
@@ -182,7 +182,7 @@ export default class FWTask implements FW.Task {
|
|
|
182
182
|
requestAnimationFrame(async () => await this.executeFrame());
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
getPerformanceReport(): FW.
|
|
185
|
+
getPerformanceReport(): FW.TaskPerformanceReport {
|
|
186
186
|
const frameTimes = this.performanceData.frameTimes;
|
|
187
187
|
const avgFrameTime = frameTimes.reduce((sum, t) => sum + t, 0) / frameTimes.length || 0;
|
|
188
188
|
|