Skip to content

[refactor] split init/start, add onReady/onDBReady/onProgress interfaces and improve error handling#453

Merged
star-e merged 20 commits intococos:mainfrom
Changdw:assets-refactor
Mar 18, 2026
Merged

[refactor] split init/start, add onReady/onDBReady/onProgress interfaces and improve error handling#453
star-e merged 20 commits intococos:mainfrom
Changdw:assets-refactor

Conversation

@Changdw
Copy link
Contributor

@Changdw Changdw commented Mar 9, 2026

[refactor] split init/start interfaces and improve error handling

Changdw added 4 commits March 9, 2026 15:27
- 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
@Changdw Changdw changed the title [refactor] split init/start interfaces and improve error handling [refactor] split init/start, add onReady/onDBReady/onProgress interfaces and improve error handling Mar 9, 2026
private _emitProgress(asset: VirtualAsset) {
if (!assetDBManager.ready) {
const { current, total } = asset._assetDB.assetProgressInfo;
this.emit('progress', current, total, asset.url);
Copy link
Contributor

@yanOO1497 yanOO1497 Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asset._assetDB 是单个 db 的启动进度,onProgress 是完整数据,所有 db 的

private _emitProgress(asset: VirtualAsset) {
if (!assetDBManager.ready) {
const { current, total } = asset._assetDB.assetProgressInfo;
this.emit('progress', current, total, asset.url);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上层可能需要制作更有语义化的消息文本,比如 正在导入 xxx ,xxx 导入完成之类的,除了 url 以外还需要一个资源的导入状态:正在导入,导入完成,导入失败,asset 对象上找一下,记得有这个数据。

db.removeListener('deleted', assetManager._onAssetDeleted.bind(assetManager));
}

private _emitProgress(asset: VirtualAsset) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里应该用 IAsset 比较好,常规 Asset 和 VirtualAsset 的并集二选一

return;
}
if ('_assetDB' in asset) {
this._emitProgress(asset as VirtualAsset);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

理论上这里不应该需要 as ,否则 _emitProgress 函数里就可能使用到不存在的字段。

console.log(`asset-change ${asset.url}`);
return;
}
if ('_assetDB' in asset) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

理论上不需要 if ,子资源的导入也是需要的,因为都影响到启动时长。

Changdw added 4 commits March 9, 2026 18:22
- 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

_onAssetDBRemoved(db: AssetDB) {
db.removeListener('unresponsive', onUnResponsive);
db.removeListener('add', assetManager._onAssetAdd.bind(assetManager));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这部分只给进度使用的监听,应该在 ready 后就移除监听

* @param listener 回调函数,接收启动完成的 dbName
* @returns 移除监听的函数
*/
onDBReady(listener: (dbName: string) => void) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

回调直接给 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
db.on('changed', assetManager._onAssetChanged.bind(assetManager));
db.on('deleted', assetManager._onAssetDeleted.bind(assetManager));
// 启动阶段的进度追踪监听器(ready 后会被移除)
db.on('add', assetManager._onAssetAdd);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里需要判断是否已经 ready 再做监听,整个 db ready 后可能会有其他插件注册 db 数据库,再进来执行这段逻辑。

}

private _emitProgress(asset: IAsset, state: 'processing' | 'success' | 'failed') {
if (!assetDBManager.ready) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

假如上层调用 _emitProgress 链路上都已经判断 ready 状态,这里是可以不需要的,只作为更原子化的方法

Changdw added 9 commits March 10, 2026 16:15
- 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
@star-e star-e merged commit e43a3f8 into cocos:main Mar 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants