Skip to content

一、总览时序(按网络请求发出顺序)

时间轴 ──────────────────────────────────────────────────────────────────────►

GooseHomeApp.onLoad()

 ├─ Game.bootstrap(this.node)  ← 幂等入口
 │   │
 │   ├─ [0] _installGlobalErrorHandlers()        ⬛ 纯同步
 │   ├─ [0.05] initEarlyDetector()               ⬛ wx.onShow 注册
 │   ├─ [0.1] initApi()                          ⬛ t-comm 网络层初始化
 │   │
 │   ├─ [0.02] preloadGroupWhenIdle(AuthBoot)    🟡 CDN 预热 5 张图(fire-and-forget)
 │   │
 │   ├─ [0.1] ServerTime.sync()                  🌐 GetTs ×1         ← 网络 #1
 │   ├─        syncFangshuaParams()              ⬛ 同步(读本地 loginInfo)
 │   ├─        ServerTime.startAutoSync()        ⬛ 设 5min 定时器
 │   │
 │   ├─ [★] PlayerService.ins.bootstrap()        🌐 GetPlayer ×1     ← 网络 #2 (fire-and-forget!)
 │   │        └─ _doBootstrap() → getPlayerInfo({})
 │   │
 │   ├─ oops.gui.init(rootNode)                  ⬛ 同步
 │   ├─ oops.storage.setUser('guest')            ⬛ 同步
 │   ├─ _registerUIs()                           ⬛ 同步(lazy factory)
 │   ├─ GooseService.ins.init()                  ⬛ 同步(本地玩法 load)
 │   │
 │   ├─ BazaarService.ins.fetchActInfo()         🌐 GetLottActInfo    ← 网络 #3 (fire-and-forget)
 │   ├─ _initWxShare()                           ⬛ 同步
 │   │
 │   ├─ AccountService.configure({...})          ⬛ 同步(注入回调)
 │   │   └─ .handleAppOnLaunch()                 ⬛ 同步(QQ 插件检查)
 │   │
 │   ├─ _installLayEggWatcher()                  ⬛ 同步(事件监听)
 │   ├─ _installDailySignInWatcher()             ⬛ 同步(事件监听)
 │   ├─ _installReportWatcher()                  🌐 home_page_exposure ← 上报 #1 (fire-and-forget)
 │   ├─ _installAccountSwitchWatcher()           ⬛ 同步(事件监听)
 │   │
 │   ├─ Director.EVENT_BEFORE_SCENE_LOADING hook ⬛ 同步
 │   │
 │   └─ oops.markReady() → dispatch AppLaunch   ⬛ 同步

 ├─ WidgetManagerPatch.apply()                   ⬛ 同步
 ├─ ResolutionGuard.install()                    ⬛ 同步

 ├─ await buildScene()                           ⬛ 同步(纯代码 UI 构建)
 │   └─ oops.gui.init(this.node)                 ⬛ 重建 layer 节点

 ├─ _subscribeServiceEvents()                    ⬛ 同步
 ├─ _onStateChanged(...)                         ⬛ 同步
 ├─ _refreshEggLabels / _refreshMarketRedPoint   ⬛ 同步(从 BazaarService 缓存读)

 ├─ [★★] BazaarService.ins.fetchInfo()           🌐 QueryExchangeInfo  ← 网络 #4 (fire-and-forget)

 ├─ schedule(showIdleReaction, 5)                ⬛ 同步

 └─ BootService.ins.run(this.node)               ⬛ 同步
     ├─ dispatch BootStarted
     ├─ GoodsDetailService.ins.init()            ⬛ 同步
     └─ dispatch BootCompleted

          └─► GooseHomeApp._onBootCompleted()
               └─ void _gateBootFlow()

                    ├─ [★★★] await PlayerService.ins.bootstrap()  ← 复用 bootstrapPromise,不再重复请求!
                    │         (改造前:isUnauthorized() 裸调 getPlayerInfo → 第 2 次 GetPlayer ❌)

                    └─ _stepAuth()

                    ┌────┴────────────────────────────────────┐
                    │  无 uid → open AuthPage                 │  有 uid → _stepAdopt()
                    │   └─ 用户点登录                          │   ├─ PetService.refresh()  🌐 GetPetInfo
                    │     └─ AccountService.switchToWx/QQ     │   ├─ 无宠 → 播领养视频 → AdoptPage
                    │       └─ code2WxLogin/code2QQLogin      │   │   └─ 用户取名提交
                    │         └─ GetPlayer (loginMp)          │   │     └─ _afterAdopt → _stepGuide
                    │           └─ bootstrap({force:true})    │   └─ 有宠 → _stepGuide()
                    │             └─ 再次 GetPlayer(register) │         ├─ 未完成 → open GuidePage
                    │               └─ onLoginSuccess         │         └─ 已完成 → _afterGuide()
                    │                 └─ dispatch AuthAccepted│
                    │                   └─ _afterAuth         │
                    │                     └─ _stepAdopt       │
                    └─────────────────────────────────────────┘

二、_afterGuide() 触发的后续请求

_afterGuide()
 ├─ gameLayer.active = true                      ⬛ 主页显示
 ├─ showToast / showBubble                       ⬛ 纯本地

 ├─ _checkAndUpdateBumpEntry()                   🌐 GetBumpConfig (via MainHomeBuilder.checkBumpActivity)
 ├─ _startBumpBackgroundScanIfAuthorized()       🟡 蓝牙 BLE(非网络,仅授权用户)

 ├─ TaskService.ins.fetchTaskList()              🌐 QueryDynaTaskByActId  ← 网络 #5

 ├─ ResManager.preloadGroupWhenIdle(HomeIdleHigh) 🟡 CDN 预热(idle 窗口后)

 ├─ GooseBehaviorTrigger.ins.evaluate()          ⬛ 纯本地(读缓存)

 └─ _checkAndUnequipExpiredCostumes()
     └─ PetService.refresh()                     🌐 GetPetInfo ×1(去重)

三、冷启动首屏网络请求清单(按发出顺序)

#接口触发位置阻塞?备注
1GetTsServerTime.sync()❌ fire-and-forget时间校准
2GetPlayerPlayerService.bootstrap()❌ fire-and-forget(但 _gateBootFlow await 它)玩家数据
3GetLottActInfoBazaarService.fetchActInfo()活动配置(规则/分享/行为文案)
4QueryExchangeInfoBazaarService.fetchInfo()金银蛋余额 + 商品列表
5GetRainbowConfigrainbow-config(被 fetchActInfo 内部触发)七彩石远程配置
6CommReportReportService 上报曝光/活跃
7GetPetInfo_stepAdopt → PetService.refresh()✅ 门控链路宠物数据
8QueryDynaTaskByActId_afterGuide → TaskService.fetchTaskList()任务列表(红点)
9GetBumpConfig_afterGuide → _checkAndUpdateBumpEntry()碰一碰入口显隐
10GetPetInfo_afterGuide → _checkAndUnequipExpiredCostumes()装扮过期检查

四、关键路径(影响首屏白屏时长)

[关键路径] = 用户看到主页的最短等待

GooseHomeApp.onLoad
  → buildScene()                           ~50ms(纯代码 UI,无 IO)
  → BootService.run()                      ~0ms(同步 dispatch)
  → _gateBootFlow()
      → await PlayerService.bootstrap()    ~200-400ms ← 🔴 网络瓶颈 #1
  → _stepAuth()
      → (已登录用户) _stepAdopt()
          → await PetService.refresh()     ~100-200ms ← 🔴 网络瓶颈 #2
      → _stepGuide()
          → _afterGuide()
              → gameLayer.active = true    ← 🎉 主页可见!

总计关键路径 ≈ 50 + max(GetPlayer, PetInfo串行) ≈ 350-600ms

五、优化建议

🔴 P0 — 已修复

问题原因修复
GetPlayer 重复请求 ×2_gateBootFlowisUnauthorized()(裸调 getPlayerInfo)绕过了 bootstrapPromise 去重✅ 改用 await PlayerService.ins.bootstrap() 复用去重 Promise

🟡 P1 — 可优化

#问题影响建议
1GetPlayer 与 GetPetInfo 串行门控链路 350-600ms(两个接口各 150-300ms 串行)PetService.refresh() 并入 _doBootstrap 内部用 Promise.all 并行,门控路径缩短 ~150ms
2BazaarService.fetchInfo() 在 buildScene 内同步触发占 L142 位置,实际不阻塞但被 buildScene 进度覆盖;与 _afterGuide 无关联移到 Game.bootstrap()fetchActInfo 并行,提前 ~50ms
3_afterGuide 内 PetService.refresh() 再次调用_checkAndUnequipExpiredCostumes 第 368 行再 refresh 一次,理论上 _stepAdopt 刚拉过就有缓存PetService._fetchPromise 去重(已有),确认无冗余
4GetTs ×2截图显示两次 GetTs?tstamp=... 完全相同的请求ServerTime.sync() 被调两次?检查是否有 startAutoSync 立即触发了一次
5CommReport ×3截图显示 3 次 CommReport(home_exposure + active + dailySignIn)正常,但可合并为单次 batch 上报减少连接数

🟢 P2 — 可清理

#代码说明
1GooseHomeApp L141-143 console.log('1111') / console.log('222')调试残留,应删除
2GooseHomeApp L147 console.log('_refreshFeedAmountLabel')调试残留,应删除
3BootService L49 console.log('[BootService] dispatching BootCompleted')调试残留,改 oops.log.logBusiness 或删除
4GooseHomeApp._gateBootFlow L195-198 注释掉的 PetService.refresh 代码块已确认不需要,删除注释
5Game._reportWatcher L634 console.log('[onLoginSuccess]')调试残留,改 oops.log.logBusiness

🔵 P3 — 架构向(后续迭代)

#方向收益
1PlayerService.bootstrap() 内部并行 GetPlayer + GetPetInfo + GetBumpConfig门控链路 600ms → 300ms
2BootService 已退化为纯 dispatcher,可内联到 GooseHomeApp.onLoad 删掉一层抽象代码简化
3BazaarService.fetchActInfo() + fetchInfo() 合并为单次初始化调用减少调用点,避免遗漏
4首屏关键路径请求走 wx.request 并发上限(微信最多 10 并发),当前无冲突,未来加请求需关注预防

六、各 Service 启动职责速查

Service启动时机触发方式做了什么
PlayerServiceGame.bootstrap L162bootstrap() fire-and-forgetGetPlayer → 落 state → dispatch PlayerLoaded + LoginSuccess
GooseServiceGame.bootstrap L178init() 同步从 oops.storage 加载本地玩法数据
BazaarServiceGame.bootstrap L184 / GooseHomeApp L142fetchActInfo() + fetchInfo()GetLottActInfo + QueryExchangeInfo
BootServiceGooseHomeApp.onLoad L153run(node) 同步dispatch BootStarted + BootCompleted
PetService_stepAdopt L233refresh() asyncGetPetInfo → 落 pets → dispatch PetInfoLoaded
TaskService_afterGuide L310fetchTaskList() asyncQueryDynaTaskByActId → 落 list → dispatch TaskListUpdated
BumpService_afterGuide L304startBackgroundScan() async蓝牙 BLE 广播+扫描(仅授权用户)
CostumeSkinService_afterGuide L398syncSavedKey() 同步装扮过期检查后同步本地 key
AccountServiceGame.bootstrap L197configure() 同步注入 QQ/微信切号回调
ServerTimeGame.bootstrap L159sync() + startAutoSync()GetTs → 校准时钟
ReportServiceGame.bootstrap L630homePageExposure()首屏曝光上报
GoodsDetailServiceBootService.run L48init() 同步注册策略工厂