JavaScript基礎數據類型BigInt實踐,JSON-bigint,bignumber.js,JavaScript精度問題 ...
項目開發中前後端數據交互常會使用id作為主鍵索引,通常id數值都不大,使用number類型就可以表示處理,但對於一些分散式id或其他情況,id數值太大且超過了JS的最大處理數(Math.pow(2, 53) = 9007199254740992)時就會存在精度問題:Math.pow(2, 53) + 1 = 9007199254740992;
實際例子:
當後端返回了這樣一個id數值的數據,可以看到此數值已經超過了JS的最大處理數,丟失了精度,前端此時拿到的id值是錯誤的,此時涉及id的前後端數據交互,前端傳輸的參數id為1528669910682108000,後端無法根據此id找到對應的數據或者找出了其他數據導致異常
可以通過瀏覽器控制台Network的Preview和Response查看差異。Response中是原始響應數據,這裡的id是正確的為1528669910682107904。而Preview中是瀏覽器接收到Response,通過JS轉化為JavaScript對象形式,並格式化層級結構,以便查看,此時經過了JS處理,id數值精度丟失,看到的就是1528669910682108000這個錯誤id,前端請求後接收到的id也是這個錯誤id。
解決辦法一:通過後端解決,把id轉化為字元串類型返回
這樣獲取到的id就是正確的id了,但是後端有數據類型嚴格定義,不願意改的話,那就靠我們前端來解決(方法二)
解決辦法二:JavaScript新增的基礎數據類型bigint就可以解決此類問題
將id轉化為bigint類型,使用到json-bigint插件處理json數據中的這類數值
npm install -S json-bigint 底層依賴於bignumber.js
然後在請求方法文件中import JSONBigInt from 'json-bigint';
在請求函數中添加這一段轉化代碼,此時可以console.log出接收到的id為
其他地方不需要改動,這個時候前後端數據交互時id參數傳輸的時候會自動轉化為字元串類型傳輸{id: "1528669910682107904"}
但是新問題又來了,現在是vue+element-ui項目,table表格綁定row-key="id",此時會報錯
解決辦法一:寫一個全局轉化函數
function transId(row) { return row.id.toString(); }
然後在使用到id的地方調用此函數,轉化為字元串類型去處理eg: (:row-key="transId")
解決辦法二:在之前import JSONBigInt的地方添加代碼:
const JSONBigIntStr = JSONBigInt({ storeAsString: true });
自動將BigNumber轉化為字元串類型,然後修改轉化代碼
這樣console.log出id就不為BigNumber類型的了,而是字元串類型,且id和後臺的id能夠對應得上