hookehuyr

refactor(离线缓存): 优化网络监听器注销逻辑并添加注释

确保网络监听器注销时的状态闭环
添加详细的类型定义和代码注释
1 /* 1 /*
2 * @Date: 2025-06-28 10:33:00 2 * @Date: 2025-06-28 10:33:00
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2026-01-17 00:22:34 4 + * @LastEditTime: 2026-01-17 12:14:16
5 * @FilePath: /xyxBooking-weapp/src/app.js 5 * @FilePath: /xyxBooking-weapp/src/app.js
6 * @Description: 应用入口文件 6 * @Description: 应用入口文件
7 */ 7 */
...@@ -168,6 +168,7 @@ const App = createApp({ ...@@ -168,6 +168,7 @@ const App = createApp({
168 * - 尝试在网络可用时预加载离线预约数据 168 * - 尝试在网络可用时预加载离线预约数据
169 * - 启动离线预约缓存轮询(会自行处理网络可用性与引用计数) 169 * - 启动离线预约缓存轮询(会自行处理网络可用性与引用计数)
170 */ 170 */
171 +
171 const bootstrap_after_auth = () => { 172 const bootstrap_after_auth = () => {
172 try_preload_when_online() 173 try_preload_when_online()
173 enable_offline_booking_cache_polling({ interval_ms: 2 * 1000 * 60 }) 174 enable_offline_booking_cache_polling({ interval_ms: 2 * 1000 * 60 })
...@@ -184,6 +185,8 @@ const App = createApp({ ...@@ -184,6 +185,8 @@ const App = createApp({
184 * - 授权成功后调用 bootstrap_after_auth 启动共用逻辑 185 * - 授权成功后调用 bootstrap_after_auth 启动共用逻辑
185 * - 授权失败则跳转至授权页面 186 * - 授权失败则跳转至授权页面
186 */ 187 */
188 +
189 + // 如果用户已授权,则直接调用 bootstrap_after_auth 启动共用逻辑
187 if (hasAuth()) { 190 if (hasAuth()) {
188 bootstrap_after_auth() 191 bootstrap_after_auth()
189 return 192 return
......
...@@ -8,6 +8,7 @@ import { get_network_type, is_usable_network } from '@/utils/network' ...@@ -8,6 +8,7 @@ import { get_network_type, is_usable_network } from '@/utils/network'
8 8
9 /** 9 /**
10 * @description: 轮询状态 10 * @description: 轮询状态
11 + * @typedef {Object} PollingState
11 * @property {Number} timer_id 轮询定时器id 12 * @property {Number} timer_id 轮询定时器id
12 * @property {Boolean} running 是否正在轮询 13 * @property {Boolean} running 是否正在轮询
13 * @property {Boolean} in_flight 是否正在刷新 14 * @property {Boolean} in_flight 是否正在刷新
...@@ -20,6 +21,7 @@ import { get_network_type, is_usable_network } from '@/utils/network' ...@@ -20,6 +21,7 @@ import { get_network_type, is_usable_network } from '@/utils/network'
20 * @property {Promise} network_listener_promise 网络监听器Promise 21 * @property {Promise} network_listener_promise 网络监听器Promise
21 */ 22 */
22 23
24 +/** @type {PollingState} */
23 const polling_state = { 25 const polling_state = {
24 timer_id: null, // 轮询定时器id 26 timer_id: null, // 轮询定时器id
25 running: false, // 是否正在轮询 27 running: false, // 是否正在轮询
...@@ -157,19 +159,31 @@ const ensure_network_listener = async () => { ...@@ -157,19 +159,31 @@ const ensure_network_listener = async () => {
157 159
158 /** 160 /**
159 * @description: 注销网络监听器 161 * @description: 注销网络监听器
162 + * 涉及字段:
163 + * - has_network_listener:是否有注册网络监听器
164 + * - ref_count:引用计数
165 + * - network_listener:网络状态变化监听器
166 + * - network_usable:网络可用性状态
160 */ 167 */
161 168
162 const teardown_network_listener = () => { 169 const teardown_network_listener = () => {
170 + // 1. 前置校验:避免无效执行
171 + // 如果没有注册网络监听器,直接返回
163 if (!polling_state.has_network_listener) return 172 if (!polling_state.has_network_listener) return
173 + // 如果有引用计数,说明有其他地方在使用轮询,不能注销监听器
164 if (polling_state.ref_count > 0) return 174 if (polling_state.ref_count > 0) return
175 + // 标记监听器已注销(核心状态更新)
165 polling_state.has_network_listener = false 176 polling_state.has_network_listener = false
177 + // 解绑框架层面的监听器
166 if (polling_state.network_listener && typeof Taro.offNetworkStatusChange === 'function') { 178 if (polling_state.network_listener && typeof Taro.offNetworkStatusChange === 'function') {
167 try { 179 try {
168 Taro.offNetworkStatusChange(polling_state.network_listener) 180 Taro.offNetworkStatusChange(polling_state.network_listener)
169 } catch (e) { 181 } catch (e) {
170 - polling_state.network_listener = null 182 + // 捕获解绑失败的异常(比如监听器已被手动解绑)
183 + console.warn('注销网络监听器失败:', e)
171 } 184 }
172 } 185 }
186 + // 手动清空本地引用(关键!无论解绑成功/失败都要做)
173 // 注销后,清空网络监听器引用,确保后续调用能正常工作 187 // 注销后,清空网络监听器引用,确保后续调用能正常工作
174 polling_state.network_listener = null 188 polling_state.network_listener = null
175 /** 189 /**
...@@ -178,6 +192,7 @@ const teardown_network_listener = () => { ...@@ -178,6 +192,7 @@ const teardown_network_listener = () => {
178 * 设计思维:体现了 “状态闭环” 的工程化思想 —— 任何状态都要有明确的产生、更新、销毁逻辑,不残留 “脏数据” 干扰后续流程。 192 * 设计思维:体现了 “状态闭环” 的工程化思想 —— 任何状态都要有明确的产生、更新、销毁逻辑,不残留 “脏数据” 干扰后续流程。
179 */ 193 */
180 // 清空网络可用性状态,确保后续判断逻辑能正常工作 194 // 清空网络可用性状态,确保后续判断逻辑能正常工作
195 + // 清空衍生状态,避免脏数据
181 polling_state.network_usable = null 196 polling_state.network_usable = null
182 } 197 }
183 198
......