问题的背景:
当接口返回的Nubmer类型id长度超过16位,js在把返回的数据转为JSON格式时,会把长度超过16位的Number类型的数据做处理,处理的方式的裁取前十六位,十六位以后的数字都补为0.
(吐槽:不理解这种处理方式是咋样的脑回路???)
首先是怎么检查出这种问题:
如图,
1.在【响应】里面,可以看到正确的数据,就是超过十六位,且十六位以后的数字不为0的数据。
2.在【预览】里面,可以看到被转化为JSON的数据,此时超过16位的Number类型的数据已经被处理为错误数据
思考为什么会出现这种问题:
参考资料:
关于JavaScript中Number整数最大长度的一个疑问_mb5fe09d2d96fc4的技术博客_51CTO博客
https://blog.51cto.com/u_15064069/3205654JS Number强类型转换数字超过16位精度丢失问题 - 简书问题图 Number转换19位(6145390195186705543)后结果为 6145390195186705000 造成原因:看网上资料说:js的number类型有个最...https://www.jianshu.com/p/d2eb9795c359百度安全验证
https://baijiahao.baidu.com/s?id=1730543232132634655&wfr=spider&for=pc总结:
js采用的是64位双精度,
最小值为:Number.MIN_SAFE_INTEGER // -9007199254740991
最大值为:Number.MAX_SAFE_INTEGER // 9007199254740991
超出规定范围导致精度丢失 console.log(900719925474099177)
解决方式:
1.如果具体业务中后台返回的id超过16位,要让后台把id改为string类型 【个人觉得这是最优解】
2.
BigInt
是一种内置对象,它提供了一种方法来表示大于2^53 - 1
的整数。这原本是 Javascript中可以用Number表示的最大数字。BigInt
可以表示任意大的整数3.拦截 【响应】的数据,用正则匹配修改 超过16位的Number类型数值 ,修改为String类型
方式三的实践:
用的是axios做http请求,在Response里面加个拦截器,用正则匹配修改 超过16位的Number类型数值 ,修改为String类型
参考资料:
拦截器 | Axios 中文文档 | Axios 中文网
https://www.axios-http.cn/docs/interceptorstransformResponse与axios的封装api_春风又一季的博客-CSDN博客_transformresponselet base = '';export const postRequest = (url, params) => { return axios({ method: 'post', url: `${base}${url}`,//Es6新语法 `${}` data: params, /* // `transformResponse` 在传递给 then/catch 前,允许修改响应数据 transformResponse: [function
https://blog.csdn.net/qq_40183281/article/details/107446718
export function QueryByPage(query) { return fetch({ url: '/lapi/bankAccount/QueryByPage', method: 'post', data: query, behaviorRecord: { name: '银行账户查询-查询列表' }, transformResponse: [function (data) { try { // 对 data 进行任意转换处理 // /^\d{m,n}$/ let reg = /\d{9,30}/g const tarArr = data.match(reg) const repArr = [] // 最终输出的json let resutlt = JSON.parse(data) if (Array.isArray(tarArr)) { for (let rep of tarArr) { repArr.push({ key: [rep], val: Number(rep) }) } } if (Array.isArray(resutlt.data.records) && resutlt.data.records.length > 0) { resutlt.data.records = resutlt.data.records.map(item => { item.id = repArr.find(obj => obj.val === item.id).key return item }) } return resutlt } catch (error) { console.error(error) } }] }); }
其他的方式,思路也大同小异,主要是对原始数据做拦截,然后把超长的Numer数据替换为String类型即可。