分享今天卡到陰,耗掉我半小時青春的鬼問題。
有個待辦事項清單網頁,使用者可點選待辦項目以 Modal Dialog 連上位於其他主機的網頁執行作業,待 Modal Dialog 關閉,待辦清單需依據執行結果決定是否將該筆作業註記為已完成,避免重複處理。由於待辦清單與執行作業網站分處不同伺服器,跨站台情境無法使用 returnValue 傳回結果,故我會靠另設狀態程式從中傳話以克服限制。(細節可參考 TIPS-跨Domain傳遞Modal Dialog結果)
情境示意如下:
//開啟另一台主機的網頁處理資料
var url = "httq://serverB/edit?id=" + item.Id;
//在url後方加上callback以更新狀態
var fixedUrl = url + "&xss_cb=" + encodeURIComponent("http://serverA/update_state?id=" + item.Id);
//使用Modal Dialog模式開啟serverB上的網頁,若作業成功呼叫xss_cbo傳入的serverA網址更新狀態
window.showModalDialog(fixedUrl, window);
//Modal Dialog關閉後檢查狀態是否更新已完成
$.get("check_state?id=" + item.Id ).done((res) => {
if (res == "OK") {
//將該筆資料註記為已完成
}
});
同事報案,這段狀態更新機制怪怪的,有時執行動作卻沒註記完成,有時則明明沒執行,只是關閉視窗項目就被標為完成,歸納不出什麼規則。
將測試拉回我的主機進行分析,在 JavaScript 加入 alert() / console.log() 試了一陣子,結果依然好時壞,動用 F12 開發者工具跟 Fidller,依然沒頭緒。
不久後,我發現一個現象,每當開啟 IE F12 開發者工具設了中斷點偵錯,程式就運作正常,關閉 F12 Bug 就開始作怪,再開啟 F12 想一探究竟又消失,這 Bug 彷彿有靈性似的... Orz
鬼打牆近十分鐘,從 Fiddler 再找到一條線索 - 關閉 F12 出問題時,Fiddler 不會出現 $.get("check_state?id=…") 封包! 但由 console.log() 軌跡則顯示 $.get() 有被執行。
啊! 是 Cache!!!
我也瞬間明白,為什麼一開 F12 時網頁就正常。答案就在下圖中,我的 $.get() 網址忘了加入亂數,因網址相同有可能會讀到先前 Cache 的內容;開啟 F12 時,因啟用了「一律從伺服器重新整理」,排除被 Cache 誤導的可能,網頁就正常了。
問題在將 "check_state?id=" + item.Id 改成 "check_state?id=" + item.Id + "&_=" + Math.random() 後修復,而我,花 30 分鐘上了一課,遇到「一開啟 F12 問題就消失」的情境,請優先檢查是否與 Cache 行為有關。