1. 从一次“诡异”的bug说起:为什么我的ID变了?
不知道你有没有遇到过这种情况:前端页面一切正常,后端接口也跑得稳稳当当,但就是有那么几个数字,传到前端之后就“变脸”了。比如,一个用户ID 1234567890123456789,在浏览器里打印出来,莫名其妙就变成了 1234567890123456700。更诡异的是,这个错误时有时无,只在某些特定的大数字上出现,调试起来简直让人抓狂。
我最近就踩了这么一个坑。项目里用户ID用的是雪花算法生成的,妥妥的Long类型(也叫大整数)。后端哥们信誓旦旦地说数据没问题,我这边用Postman测试,返回的JSON里ID也是完完整整的。可一旦数据进了我的Vue应用,经过axios那么一接手,再渲染到页面上,最后几位数字就“丢”了。用户列表里,本来独一无二的ID,竟然出现了重复,导致后续的编辑、删除操作全部指向了错误的用户,差点酿成线上事故。
问题的根源,就藏在浏览器“自作聪明”的JSON解析机制里。 JavaScript这门语言,数字只有一种类型:Number。它内部遵循IEEE 754双精度浮点数标准。这个标准有个硬伤:它能安全、精确表示的整数范围是有限的,在 -(2^53 - 1) 到 (2^53 - 1) 之间(也就是大约正负9千万亿)。一旦数字超过这个范围,比如我们雪花算法生成的、动辄19位的Long型ID,精度丢失就不可避免了。浏览器内置的 JSON.parse() 方法,在遇到一个纯数字的JSON字段时,会毫不犹豫地把它转换成 Number 类型。一旦这个数字超出了安全整数范围,转换过程就会发生“四舍五入”式的精度丢失,而且这个过程是静默发生的,不会报任何错误,这才是最可怕的地方。
所以,我们需要的不是更好的算法,而是一个“外援”——一个能绕过浏览器原生解析,把JSON字符串中的大数字,原原本本、一字不差地识别出来的工具。这就是我们今天的男主角:json-bigint 库。而axios的拦截器,就是我们请这位“外援”登场的最佳舞台。整个思路就是:“瞒天过海”。我们先告诉axios:“别动我的数据,把它当成纯文本(responseType: 'text')给我。” 然后,在数据到达业务代码之前,用拦截器这个“中间人”,请出 json-bigint 这位专家来精准解析。下面,我们就一步步拆解这个优雅的解决方案。
2. 核心武器拆解:认识 json-bigint
在动手改造axios之前,我们得先摸清手里这把“武器”的脾性。json-bigint 是一个纯JavaScript编写的库,它干了一件很专一但又至关重要的事:在解析JSON时,将超过JavaScript安全整数范围的数字,自动转换为 BigInt 类型,或者你指定的字符串格式,从而完美保留精度。
为什么是 BigInt?这是ES2020引入的一种新的基本数据类型,专门用来表示任意精度的整数。你在数字后面加个 n,比如 1234567890123456789n,这就是一个 BigInt。它可以表示远超 Number 类型限制的整数,且运算精确。json-bigint 默认就会把大数字转成 BigInt。
我们来快速感受一下它的威力。先安装它:
npm install json-bigint
如果你的项目是TypeScript的,为了获得良好的类型提示,建议也装上类型声明文件:
npm install --save-dev @types/json-bigint
然后,看一个最简单的对比示例:
import JSONbig from 'json-bigint';
// 一个包含大数字的JSON字符串
const jsonString = '{"id": 1234567890123456789, "name": "test"}';
// 使用浏览器原生 JSON.parse
const nativeResult = JSON.parse(jsonString);
console.log('原生解析:', nativeResult.id); // 输出: 1234567890123456700 (精度丢失!)
console.log('类型:', typeof nativeResult.id); // 输出: number
// 使用 json-bigint 解析
const bigIntResult = JSONbig.parse(jsonString);
console.log('json-bigint解析:', bigIntResult.id.toString()); // 输出: 1234567890123456789 (完美!)
console.log('类型:',


611

被折叠的 条评论
为什么被折叠?



