分享今天卡到陰,耗掉我半小時青春的鬼問題。

有個待辦事項清單網頁,使用者可點選待辦項目以 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 + "&_=" + (new Date().getTime()) 後修復,而我,花 30 分鐘上了一課,遇到「一開啟 F12 問題就消失」的情境,請優先檢查是否與 Cache 行為有關。(註:Chrome F12 也有 Disable Cache 選項,類似現象也可能上演)

註: 關於加參數避免 Cache 的寫法,除了自己在 URL 加上亂數或 Timestamp(亂數仍存在極低的重複機率,一般循序執行下時間值無重複風險,是更好的選擇),還可改寫成 $.ajax({ url: "check_state", data: { id: item.Id }, cache: false}) 由 jQuery 加上 Timestamp 避免讀取 Cache。(感謝大家留言提醒) 參考: jQuery.ajax() - jQuery API Documentation邊做邊學jQuery系列14 - 呼叫總部-jQuery.ajax()


Comments

# by 路過

Jquery的$.ajax()其中有一個屬性是cache可以設成false https://api.jquery.com/jQuery.ajax/

# by Jeffrey

to 路過,感謝提醒,已補充本文。

Post a comment


47 + 12 =