refactor(网络请求): 重构弱网处理逻辑并移除组件中的超时代码
将弱网和超时处理逻辑集中到请求拦截器中 移除组件中冗余的超时处理代码 添加离线预约缓存检查功能
Showing
2 changed files
with
97 additions
and
13 deletions
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2024-01-16 10:06:47 | 2 | * @Date: 2024-01-16 10:06:47 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2026-01-13 15:18:07 | 4 | + * @LastEditTime: 2026-01-13 16:00:44 |
| 5 | * @FilePath: /xyxBooking-weapp/src/components/qrCode.vue | 5 | * @FilePath: /xyxBooking-weapp/src/components/qrCode.vue |
| 6 | * @Description: 预约码卡组件 | 6 | * @Description: 预约码卡组件 |
| 7 | --> | 7 | --> |
| ... | @@ -169,12 +169,7 @@ const formatGroup = (data) => { | ... | @@ -169,12 +169,7 @@ const formatGroup = (data) => { |
| 169 | const init = async () => { | 169 | const init = async () => { |
| 170 | if (!props.type) { | 170 | if (!props.type) { |
| 171 | try { | 171 | try { |
| 172 | - // TAG: 设置 5s 超时判定为弱网 | 172 | + const { code, data } = await qrcodeListAPI(); |
| 173 | - const timeoutPromise = new Promise((_, reject) => { | ||
| 174 | - setTimeout(() => reject(new Error('TIMEOUT')), 5000); | ||
| 175 | - }); | ||
| 176 | - | ||
| 177 | - const { code, data } = await Promise.race([qrcodeListAPI(), timeoutPromise]); | ||
| 178 | 173 | ||
| 179 | if (code) { | 174 | if (code) { |
| 180 | data.forEach(item => { | 175 | data.forEach(item => { |
| ... | @@ -194,10 +189,6 @@ const init = async () => { | ... | @@ -194,10 +189,6 @@ const init = async () => { |
| 194 | } | 189 | } |
| 195 | } catch (err) { | 190 | } catch (err) { |
| 196 | console.error('Fetch QR List Failed:', err); | 191 | console.error('Fetch QR List Failed:', err); |
| 197 | - // 如果是超时,跳转弱网页面 | ||
| 198 | - if (err.message === 'TIMEOUT') { | ||
| 199 | - go('/pages/weakNetwork/index'); | ||
| 200 | - } | ||
| 201 | } | 192 | } |
| 202 | } else { | 193 | } else { |
| 203 | if (props.payId) { | 194 | if (props.payId) { | ... | ... |
| 1 | /* | 1 | /* |
| 2 | * @Date: 2022-09-19 14:11:06 | 2 | * @Date: 2022-09-19 14:11:06 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2026-01-08 19:25:17 | 4 | + * @LastEditTime: 2026-01-13 16:15:35 |
| 5 | * @FilePath: /xyxBooking-weapp/src/utils/request.js | 5 | * @FilePath: /xyxBooking-weapp/src/utils/request.js |
| 6 | * @Description: 简单axios封装,后续按实际处理 | 6 | * @Description: 简单axios封装,后续按实际处理 |
| 7 | */ | 7 | */ |
| ... | @@ -11,6 +11,7 @@ import Taro from '@tarojs/taro' | ... | @@ -11,6 +11,7 @@ import Taro from '@tarojs/taro' |
| 11 | // import qs from 'qs' | 11 | // import qs from 'qs' |
| 12 | // import { strExist } from './tools' | 12 | // import { strExist } from './tools' |
| 13 | import { refreshSession, saveCurrentPagePath, navigateToAuth } from './authRedirect' | 13 | import { refreshSession, saveCurrentPagePath, navigateToAuth } from './authRedirect' |
| 14 | +import { has_offline_booking_cache } from '@/composables/useOfflineBookingCache' | ||
| 14 | 15 | ||
| 15 | // import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress'; | 16 | // import { ProgressStart, ProgressEnd } from '@/components/axios-progress/progress'; |
| 16 | // import store from '@/store' | 17 | // import store from '@/store' |
| ... | @@ -46,6 +47,95 @@ service.defaults.params = { | ... | @@ -46,6 +47,95 @@ service.defaults.params = { |
| 46 | ...REQUEST_DEFAULT_PARAMS, | 47 | ...REQUEST_DEFAULT_PARAMS, |
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 50 | +let has_shown_timeout_modal = false | ||
| 51 | + | ||
| 52 | +/** | ||
| 53 | + * 判断是否为超时错误 | ||
| 54 | + * @param {Error} error - 请求错误对象 | ||
| 55 | + * @returns {boolean} 是否为超时错误 | ||
| 56 | + */ | ||
| 57 | + | ||
| 58 | +const is_timeout_error = (error) => { | ||
| 59 | + const msg = String(error?.message || error?.errMsg || '') | ||
| 60 | + if (error?.code === 'ECONNABORTED') return true | ||
| 61 | + return msg.toLowerCase().includes('timeout') | ||
| 62 | +} | ||
| 63 | + | ||
| 64 | +/** | ||
| 65 | + * 判断是否为网络错误(断网/弱网/请求失败等) | ||
| 66 | + * @param {Error} error - 请求错误对象 | ||
| 67 | + * @returns {boolean} 是否为网络错误 | ||
| 68 | + */ | ||
| 69 | +const is_network_error = (error) => { | ||
| 70 | + const msg = String(error?.message || error?.errMsg || '') | ||
| 71 | + const raw = (() => { | ||
| 72 | + try { | ||
| 73 | + return JSON.stringify(error) || '' | ||
| 74 | + } catch (e) { | ||
| 75 | + return '' | ||
| 76 | + } | ||
| 77 | + })() | ||
| 78 | + const lower = (msg + ' ' + raw).toLowerCase() | ||
| 79 | + if (lower.includes('request:fail')) return true | ||
| 80 | + if (lower.includes('request fail')) return true | ||
| 81 | + if (lower.includes('network error')) return true | ||
| 82 | + if (lower.includes('failed to fetch')) return true | ||
| 83 | + if (lower.includes('the internet connection appears to be offline')) return true | ||
| 84 | + if (lower.includes('err_blocked_by_client')) return true | ||
| 85 | + if (lower.includes('blocked_by_client')) return true | ||
| 86 | + return false | ||
| 87 | +} | ||
| 88 | + | ||
| 89 | +/** | ||
| 90 | + * 是否需要触发弱网/断网降级逻辑 | ||
| 91 | + * - 超时:直接触发 | ||
| 92 | + * - 网络错误:直接触发(避免 wifi 但无网场景漏判) | ||
| 93 | + * @param {Error} error - 请求错误对象 | ||
| 94 | + * @returns {Promise<boolean>} 是否需要触发降级 | ||
| 95 | + */ | ||
| 96 | +const should_handle_bad_network = async (error) => { | ||
| 97 | + if (is_timeout_error(error)) return true | ||
| 98 | + return is_network_error(error) | ||
| 99 | +} | ||
| 100 | + | ||
| 101 | +/** | ||
| 102 | + * 处理请求超时错误 | ||
| 103 | + * - 显示超时提示 modal | ||
| 104 | + * - 若有离线预约记录缓存,则跳转至离线预约列表页 | ||
| 105 | + * - 否则提示用户检查网络连接 | ||
| 106 | + */ | ||
| 107 | +const handle_request_timeout = async () => { | ||
| 108 | + if (has_shown_timeout_modal) return | ||
| 109 | + has_shown_timeout_modal = true | ||
| 110 | + | ||
| 111 | + const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : [] | ||
| 112 | + const current_page = pages && pages.length ? pages[pages.length - 1] : null | ||
| 113 | + const current_route = current_page?.route || '' | ||
| 114 | + if (String(current_route).includes('pages/offlineBookingList/index')) return | ||
| 115 | + | ||
| 116 | + // 若有离线预约记录缓存,则跳转至离线预约列表页 | ||
| 117 | + if (has_offline_booking_cache()) { | ||
| 118 | + try { | ||
| 119 | + await Taro.reLaunch({ url: '/pages/offlineBookingList/index' }) | ||
| 120 | + } catch (e) { | ||
| 121 | + console.error('reLaunch offlineBookingList failed:', e) | ||
| 122 | + } | ||
| 123 | + return | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + // 否则提示用户检查网络连接 | ||
| 127 | + try { | ||
| 128 | + await Taro.showModal({ | ||
| 129 | + title: '网络连接不畅', | ||
| 130 | + content: '当前网络信号较弱,暂无法使用小程序,请到网络更好的地方重试。', | ||
| 131 | + confirmText: '知道了', | ||
| 132 | + showCancel: false, | ||
| 133 | + }) | ||
| 134 | + } catch (e) { | ||
| 135 | + console.error('show weak network modal failed:', e) | ||
| 136 | + } | ||
| 137 | +} | ||
| 138 | + | ||
| 49 | // request interceptor | 139 | // request interceptor |
| 50 | service.interceptors.request.use( | 140 | service.interceptors.request.use( |
| 51 | config => { | 141 | config => { |
| ... | @@ -144,12 +234,15 @@ service.interceptors.response.use( | ... | @@ -144,12 +234,15 @@ service.interceptors.response.use( |
| 144 | 234 | ||
| 145 | return response | 235 | return response |
| 146 | }, | 236 | }, |
| 147 | - error => { | 237 | + async error => { |
| 148 | // Taro.showToast({ | 238 | // Taro.showToast({ |
| 149 | // title: error.message, | 239 | // title: error.message, |
| 150 | // icon: 'none', | 240 | // icon: 'none', |
| 151 | // duration: 2000 | 241 | // duration: 2000 |
| 152 | // }) | 242 | // }) |
| 243 | + if (await should_handle_bad_network(error)) { | ||
| 244 | + handle_request_timeout() | ||
| 245 | + } | ||
| 153 | return Promise.reject(error) | 246 | return Promise.reject(error) |
| 154 | } | 247 | } |
| 155 | ) | 248 | ) | ... | ... |
-
Please register or login to post a comment