手機 App 使用 jQuery Mobile + $.ajax({async: false}) 向後端 .ashx 請求資料,出現**「網路異常,請稍候重試!」** 且時好時壞,Chrome DevTools 顯示 NetworkError: Failed to execute 'send' on 'XMLHttpRequest'。這類間歇性失敗通常非單一原因,需系統化排查。
| 類別 | 典型徵兆 | 快速驗證 | 解決方向 |
|---|---|---|---|
| 網路層 | 弱訊號、切換基地台、Wi-Fi 斷連、Carrier NAT 逾時 | 手機開熱點給筆電抓包 (Wireshark);或 App 內集成 NetInfo 記錄連線類型/強度 | 加入重試機制 (指數退避);離線快取關鍵資料;監控 navigator.onLine |
| 伺服器/防火牆 | 同一 IP 短時間高頻請求觸發 WAF/CC 防護、應用程式池回收、資料庫連線池耗盡 | 後端 IIS/NGINX 存取日誌對比失敗時間點;檢查 WAF 封鎖記錄;啟用失敗請求追蹤 (FREB) | 調整 WAF 規則;優化後端連線池;引入 Redis 快取降低 DB 壓力 |
| 前端代碼 | async: false 阻塞主執行緒導致頁面假死、瀏覽器殺掉長時間請求;error 回調未記錄 xhr.status/xhr.responseText | 改 async: true + Promise/async-await;在 error 印出完整 xhr 物件 | 移除同步 AJAX;統一錯誤處理攔截器;加入請求 ID 便於端到端追蹤 |
error: function(xhr, status, err) {
console.error('AJAX FAIL', {
url: this.url,
status: xhr.status,
statusText: xhr.statusText,
response: xhr.responseText,
readyState: xhr.readyState,
timestamp: Date.now()
});
alert('網路異常,請稍候重試!');
}
axios-retry 或自寫):function fetchWithRetry(url, options = {}, retries = 3, delay = 500) {
return fetch(url, options).catch(e => {
if (retries === 0) throw e;
return new Promise(r => setTimeout(r, delay))
.then(() => fetchWithRetry(url, options, retries - 1, delay * 2));
});
}
GET /healthz 回傳 {status: "ok", db: "connected", queue: 12},App 啟動/定期輪詢,確認後端可用才發送業務請求。X-Request-Id: uuid Header,後端透傳至日誌、資料庫、下游服務。fetch/XMLHttpRequest 封裝為 Span,實現全鏈路可視化。async: false 係因舊版 jQuery Mobile 單頁應用架構限制,建議漸進式遷移至 Vue/React + Capacitor 或 UniApp,徹底解決同步阻塞問題。[ ] 前端 error 回調是否記錄完整 xhr 物件
[ ] 後端存取日誌是否有對應 4xx/5xx/無記錄(網路未到達)
[ ] WAF/防火牆是否有封鎖該 IP/UA 的記錄
[ ] 機房/雲廠商是否有網路抖動/維護公告
[ ] App 是否在弱網/切換網路環境下測試過
[ ] 是否已移除 async: false 改用非同步模式
[ ] 是否有客戶端重試與離線快取策略
間歇性 AJAX 失敗本質上是 **分散式系統部分失敗** 的典型表現。建立 **可觀測性 (日誌/指標/追蹤)** + **韌性模式 (重試/熔斷/快取/降級)**,才能從根本上提升行動 App 的網路穩定性。