記錄一下前幾天踩坑的經歷。
背景:一個項目某一版之后很多用easyui的表格控件treegrid渲染的表格都顯示不出來了
奇怪的地方主要有以下幾點:
- 項目在測試環境才會這樣,在本機能夠正常運行,多次重新發布后無果
- 有很多表格顯示不出來,但也有的代碼幾乎一樣的表格卻能正常顯示數據
- 重新部署曾經可以正常運行的版本后依然如此
測試環境有問題本地沒問題的情況我也是見得不少了,無論如何先F12看看
Uncaught TypeError: Cannot read property 'length' of undefined
觀察異常棧,是easyui報的這個錯,吐槽一下easyui報的錯太不友好。這樣很難看出問題,於是我又把測試服務器返回的html與本地服務器返回的html用工具進行比較,結果是只有渲染服務器地址的部分不一樣(一個是localhost一個是ip)沒看出來任何問題。觀察ajax請求的數據,只有數據的id不一樣(這是伏筆),id是后台隨機生成的用於作表格的唯一標識符,也沒有看出來問題。無奈之下,我只有debug到easyui的源碼分析原因。
一個小時后。。。
通過對比服務端和本地的代碼運行狀況,觀察差異,找到了報錯的原因:id有重復,id重復導致樹結構混亂,通過parentId查找父節點時查找到的是錯誤的父節點。這里再次吐槽一下easyui,您不能先驗證一遍id有沒有重復,有提示一下不好嗎?無論如何,我找到了報錯原因,那么接下來問題來了:為什么id會有重復?
前面有提到這里是用的是treegrid控件,這里樹有三級,后台方法使用System.nanoTime()
方法產生一個隨機數作為id設置給第二,三級樹節點。這個方法返回的是Long
值
現在一切都可以解釋了。
1.項目在測試環境才會這樣,在本機能夠正常運行,多次重新發布后無果
System.nanoTime()
產生的id會因為環境而有差異,在本地產生的id可能並未達到浮點數精度丟失的范圍,而服務端產生的id超過了,導致了精度丟失,不一樣的長整型由js處理后轉換成浮點數后得到的結果是一樣的,10000000000000000和10000000000000001得到的結果是一樣的,從而導致了id重復
2.有很多表格顯示不出來,但也有的代碼幾乎一樣的表格卻能正常顯示數據
這一點是數據的問題,表格本身幾乎一樣但數據不一樣,顯示出數據的表格沒有第三級節點,而報錯的表格有,一二級節點因為是父節點所以都有children
屬性,easyui的treegrid根據此屬性形成樹結構,而第三級節點沒有children
屬性因為它根本沒有子節點,從而導致報錯Uncaught TypeError: Cannot read property 'length' of undefined
3.重新部署曾經可以正常運行的版本后依然如此
因為相關代碼並沒有變動,這是一個地雷,早早埋下而不知何時會爆炸的地雷。
根本原因為后台返回的Long
類型數據由js處理后可能導致精度丟失。最后解決方案非常簡單,把long轉換成int就一切解決了。由此得出教訓,后台返回給js的數據不要使用Long類型。
參見:
What is JavaScript's highest integer value that a number can go to without losing precision?