今天遇到一个js中因为数字过大而导致数据传输时精度丢失,导致疯狂报错的问题(无奈),检查了好几遍代码后确定并没有写错代码,然后又回来找原因,这也好像是我第一次遇到大数字传输的问题。。。我的需求就只是通过一个很长的id值,然后发起请求并从后端获取相应的数据,最后发现是id值过长导致的报错,下面是我对这个问题的一些思考和理解
JavaScript可以很精准的来表示-2^53到2^53之间的数(不包含端点),ES6中提供了两个方法Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER来表示最高最低两个值,输出如下👇
Number.MIN_SAFE_INTEGER的值,👇
Number.MAX_SAFE_INTEGER的值,👇
在实际运用中,只要数值超过了规定的上限或者是下线,数值就有可能(概率还挺大的!!)失去精度,比如说👇将JavaScript对象转换成json字符时发生错误
let obj = {
id:90071992547410057,
name:"Tom",
age:18
}
const jsonStr = JSON.stringify(obj)
console.log(jsonStr)
输出结果👇
可以看到数值最大的id值转换后已经不准确了,再来看看从json字符串转换成JavaScript对象👇
let jsonStr = {"id":90071992547410055,"name":"Tom","age":18}
const jsStr = JSON.stringify(jsonStr)
console.log(jsStr)
输出结果👇
可以看书,超过最大限度值之后,id的无法精确的表示,实际上在前后端数据传输时,axios会自动的调用方法将数据转换成json格式,或者将json转换成js对象,但是当遇到上述问题时,数据在传输的过程中发生变化,就会导致系统直接报错,但这并不是axios的错。
为了解决这个问题,需要引入一个三方包叫json-bigint,我实在Vue.js的项目中使用的
首先是导入
import JSONbig from "json-bigint";
然后就可以直接使用了
Str: '{ "id": 90071992547410055}',
console.log(JSONbig.parse(this.Str))
先来看看这个方法,和JSON.parse()相同的用法,不过JSONbig.parse()中如果直接放入json字符串的话,返回的是一个对象中会包含一个数组,它的原理其实是将一个大的数字分割成小的数字,然后再拼接,👇90071992547410055转换成了下面这个
也即是说通过JSONbig.parse()所得的结果已经不再是字符串了,而是一个对象,要获取id值需要再后面再加上.id.toString()才行
console.log(JSONbig.parse(this.Str).id.toString())
同理的JSON.stringify()对应的就是JSONdig.stringify(),这里就不再多说了。
综上,axios既然不能帮我们做到大数字的精准,我们就需要在项目中通过“json-bigint”对axios的配置文件进行设置,思路就是在发送axios请求时加上一个transformResponse
import axios from 'axios'
import JSONbig from "json-bigint";
const request = axios.create({
baseURL: 'http://ttapi.research.itcast.cn/',
transformResponse: [function (data) {
try {
return JSONbig.parse(data)
} catch (err) {
return data
}
}]
})
这样在发送请求时大数字的数据就会被自动转换了,同时也注意,通过JSONbig转化的数据是一个对象,不同于通过JSON.的方式转化的数据,所以如果在导入了以上的代码后,由于JSONbig转化数据的类型不同可能会导致前面的一些代码报错,这个时候就需要做相应的转换即可。