😭前端好苦,经常被后端和测试骂

31 阅读2分钟

我司后端用Java的long类型(能存超级大的数字,比如雪花ID),但传到前端后,JavaScript的number类型接不住这么大数字,导致末尾几位被吞,变成00000… 比如你看到ID从1234567890123456789变成了1234567890123450000。

为啥会这样?

  • 后端(Java):long类型是64位整数,能精确表示超级大的数字(最高到19位数)
  • 前端(JavaScript):number类型用的是64位浮点数,虽然也能存大数,但精确表示的安全整数范围只有16位(2^53-1)。超过这个位数,精度就丢了!

浏览器Network里看着是对的,但JS里拿到就是错的? 因为浏览器DevTools的Network显示的是原始响应字符串(还没被JS解析),而JS拿到后会自动用JSON.parse()转成对象,就在这一步精度丢失了!

前端自救方案(治标不治本,但能应急):

  1. 最优解:后端改返回string类型(从根源解决,但需要协调)
  2. 前端拦截处理:用axios的transformResponse + json-bigint库
    • 关键:要在Axios解析JSON之前,手动用json-bigint处理原始响应字符串
    • 注意:不能先转成JS对象再处理,那时已经丢精度了!
import axios from 'axios';
import JSONbig from 'json-bigint';

const axiosInstance = axios.create({
  transformResponse: [function (data) {
    // 这里data还是字符串!直接用json-bigint解析
    return JSONbig.parse(data);
  }]
});

血泪教训:

  • 所有可能超过15位的ID(比如雪花ID、分布式ID),必须让后端返回string类型!
  • 联调时一定要测试大ID(比如18位以上的)边界情况!
  • 别再让前端背锅了!这明明是数据类型兼容的常识问题!

所以下次后端再说“我们ID就是数字”时,可以把这篇文章甩过去——不是前端菜,是科学道理就这样!

前端学点后端知识,尽量全栈,不要被人骂菜鸡了😭