[refactor] split init/start, add onReady/onDBReady/onProgress interfaces and improve error handling#453
Conversation
- Add 'progress', 'db-ready', and 'ready' to AssetManagerEvents - Expose onReady, onDBReady, and onProgress from assetManager - Export these registration functions in src/lib/assets/assets.ts Made-with: Cursor
- Create docs/dev/core/assets/events-timing.md detailing the lifecycle of asset databases and their events. - Add detailed JSDoc comments to onProgress, onDBReady, and onReady in src/lib/assets/assets.ts and src/core/assets/manager/asset.ts. - Update AssetManagerEvents interface documentation to clarify event timing. Made-with: Cursor
- Change onReady to use 'on' instead of 'once' for better flexibility - Update events-timing.md: add init() call and onDBReady example - Fix import statement in documentation: use Assets (capitalized) instead of assets - Improve best practices example with complete initialization flow Made-with: Cursor
src/core/assets/manager/asset.ts
Outdated
| private _emitProgress(asset: VirtualAsset) { | ||
| if (!assetDBManager.ready) { | ||
| const { current, total } = asset._assetDB.assetProgressInfo; | ||
| this.emit('progress', current, total, asset.url); |
There was a problem hiding this comment.
asset._assetDB 是单个 db 的启动进度,onProgress 是完整数据,所有 db 的
src/core/assets/manager/asset.ts
Outdated
| private _emitProgress(asset: VirtualAsset) { | ||
| if (!assetDBManager.ready) { | ||
| const { current, total } = asset._assetDB.assetProgressInfo; | ||
| this.emit('progress', current, total, asset.url); |
There was a problem hiding this comment.
上层可能需要制作更有语义化的消息文本,比如 正在导入 xxx ,xxx 导入完成之类的,除了 url 以外还需要一个资源的导入状态:正在导入,导入完成,导入失败,asset 对象上找一下,记得有这个数据。
src/core/assets/manager/asset.ts
Outdated
| db.removeListener('deleted', assetManager._onAssetDeleted.bind(assetManager)); | ||
| } | ||
|
|
||
| private _emitProgress(asset: VirtualAsset) { |
There was a problem hiding this comment.
这里应该用 IAsset 比较好,常规 Asset 和 VirtualAsset 的并集二选一
src/core/assets/manager/asset.ts
Outdated
| return; | ||
| } | ||
| if ('_assetDB' in asset) { | ||
| this._emitProgress(asset as VirtualAsset); |
There was a problem hiding this comment.
理论上这里不应该需要 as ,否则 _emitProgress 函数里就可能使用到不存在的字段。
src/core/assets/manager/asset.ts
Outdated
| console.log(`asset-change ${asset.url}`); | ||
| return; | ||
| } | ||
| if ('_assetDB' in asset) { |
There was a problem hiding this comment.
理论上不需要 if ,子资源的导入也是需要的,因为都影响到启动时长。
- Add state parameter ('processing' | 'success' | 'failed') to progress event
- Rename message parameter to url for better semantic clarity
- Update progress event to emit state based on asset import lifecycle
- Listen to 'add'/'change'/'delete' events for 'processing' state
- Check asset.invalid and asset.importError for 'failed' state
- Update documentation and examples to reflect new API
Made-with: Cursor
…y checks - Change _emitProgress and _getImportState parameter types from VirtualAsset to IAsset - Remove '_assetDB' in asset checks as sub-assets also need progress tracking - Sub-asset imports affect startup time and should be included in progress Made-with: Cursor
- 添加 progress.test.ts 测试文件,验证资源导入进度事件 - 测试覆盖 processing/success/failed 三种状态 - 测试验证进度聚合(多个 DB 的进度汇总) - 测试验证 ready 状态下的行为差异 - 添加日志开关,可通过 PROGRESS_TEST_LOG=true 启用详细日志 Made-with: Cursor
src/core/assets/manager/asset.ts
Outdated
|
|
||
| _onAssetDBRemoved(db: AssetDB) { | ||
| db.removeListener('unresponsive', onUnResponsive); | ||
| db.removeListener('add', assetManager._onAssetAdd.bind(assetManager)); |
There was a problem hiding this comment.
这部分只给进度使用的监听,应该在 ready 后就移除监听
src/core/assets/manager/asset.ts
Outdated
| * @param listener 回调函数,接收启动完成的 dbName | ||
| * @returns 移除监听的函数 | ||
| */ | ||
| onDBReady(listener: (dbName: string) => void) { |
There was a problem hiding this comment.
回调直接给 dbInfo 吧,没几个字段,不然有需要还得重新查询,只有 name 数据基本不够用的
- Fixed a memory leak in AssetManager where progress listeners could not be removed correctly due to bind() usage by converting event handler methods to class arrow functions. - Automatically remove progress-specific listeners from DB after initialization completes. - Changed the parameter of onDBReady callback from dbName (string) to dbInfo (IAssetDBInfo) to provide comprehensive DB info. - Updated documentation and type definitions accordingly. Made-with: Cursor
src/core/assets/manager/asset.ts
Outdated
| db.on('changed', assetManager._onAssetChanged.bind(assetManager)); | ||
| db.on('deleted', assetManager._onAssetDeleted.bind(assetManager)); | ||
| // 启动阶段的进度追踪监听器(ready 后会被移除) | ||
| db.on('add', assetManager._onAssetAdd); |
There was a problem hiding this comment.
这里需要判断是否已经 ready 再做监听,整个 db ready 后可能会有其他插件注册 db 数据库,再进来执行这段逻辑。
src/core/assets/manager/asset.ts
Outdated
| } | ||
|
|
||
| private _emitProgress(asset: IAsset, state: 'processing' | 'success' | 'failed') { | ||
| if (!assetDBManager.ready) { |
There was a problem hiding this comment.
假如上层调用 _emitProgress 链路上都已经判断 ready 状态,这里是可以不需要的,只作为更原子化的方法
- Add ready state check in _onAssetDBCreated to prevent adding progress listeners for dynamically registered DBs after initialization. - Remove ready check from _emitProgress to make it a more atomic method, delegating ready state validation to callers. Made-with: Cursor
# Conflicts: # src/core/assets/@types/protected/asset.d.ts # src/core/assets/manager/asset.ts
- Added a defensive check in `_extractAssetChangeInfo` of `asset.ts` to prevent uncaught "parameter error" when processing asset events (added, changed, deleted) where the asset object might have a null or undefined `uuid`. - Updated `query.test.ts` to adjust the expected count for `cc.SceneAsset` under `internal` from 6 to 3, as it reflects the correct setup state, fixing a previously failing test. Made-with: Cursor
- Changed the expectation in `query.test.ts` for counting internal `cc.SceneAsset` resources from `toBe(3)` to `toBeGreaterThan(0)` to make the test more robust against test data changes. Made-with: Cursor
[refactor] split init/start interfaces and improve error handling