JS坑19位数字精度损失详解
更大的
这个项目只是为了爬行体验。每次访问都会实时抓取数据,所以数据返回速度会比较慢。实际操作应该是定期抓取数据,然后将数据保存到数据库中,再从数据库中返回数据,提高数据返回效率。
但是项目很基础,可以作为以上节点模块最基础的践行者,希望能帮助大家发源
最近,当实现一个需求时,需要访问第三方的接口。首先调用接口A。接口A返回的数据包含一个taskId,然后用这个taskId请求接口B获取最终需要的数据。
后端使用节点,所以首先使用包request-promise来请求第三方接口。但是得到接口A返回的taskId并调用接口B后,接口B的响应其实是系统错误!简单的代码如下
const RP=require(' request-promise ')const { taskId }=await RP(' https://XXX.com/A ')const options={ method : ' POST ',uri: 'https://xxx.com/B ',Body: {taskid},JSON : true } const result=await RP(options)/{/'错误代码' :' 40001 ',/' message ' 3:
在反复检查代码并确保请求的参数是正常格式后,我陷入了无尽的沉思。
发现
经过几次尝试,我发现使用节点请求得到的taskId最后两位都是0,也就是1152921504735848700,而使用postman得到的taskId比较正常,就是1152921504735848759。然后我在节点控制台中执行以下操作。
那一刻,我顿悟了。接口A中的TaskId是一个19位数字,但是当request-promise将数据解析为json时,这个19位数字的精度就丢失了。检查数据后发现js的数字类型有一个最大安全值,即2的53次方(9007199254740992),超过这个值精度会丢失。下跪
获取正确的响应数据
由于开始时使用了request-promise包,因此获取的taskId失去了精度,因此改为使用节点的本机http模块发送请求。
Const req=https。request ('https://xxx.com/a ',(res)={res.on ('data ',(chunk)={//由于这里得到的响应数据是一个JSON字符串,19位数字只是字符串的一部分,获取的taskId是正确的数字console . log(` body 3333)});res.on('end ',()={ console.log('无更多数据响应');})})虽然得到的是正常的响应数据,但它是一个JSON字符串,然后这个字符串会被解析成JSON,但是使用JSON.parse()会造成精度损失的问题,这真的很尴尬Orz
如果接口是可控的,可以把19位数字转换成字符串,这样解析的时候就不会出错,但是不能更改,因为是第三方接口。那么最快的解决办法就是用不同的编程语言请求(_)
最终解决方案
好吧,最后我用了node,但是我用了一个硬核方案来实现。首先,我在JSON字符串中找到这个19位的数字,然后在上面加上引号,这样当我用JSON.parse()解析它的时候,就可以保持正常值,这样下一个进程自然会通过。代码如下
让result=' { ' taskid ' :1152921504735848759,' status' :' created ',' progress' :0.0,' success' : true}'//JSON。parse (result)不为19位数字填充双引号直接解析时精度会丢失,结果如下://{//taskid :1152921504735848700,//status:' created ',//progress33600,//success 3360 true//} const taskid=result。match(/[0-9]{ 19 }/)[0]//定期获取19位数的值result=result.replace(taskId,` ' ${taskId}'`) //填入双引号constdata=JSON。parse(result)//{//taskid : ' 1152921504735848759 ',//解析后是字符串,所以没有丢失精度//status:' created ',
Node已经用了一段时间了,因为不涉及大数的计算,所以数字和id都是以字符串的形式存储的,从来没有遇到过这个问题。这次我真的遇到了。不得不说js在这方面确实有点弱。之后我也尝试过用Go和GO,python来做请求,可以正确分析,但是node用起来还是很舒服的
以上是边肖介绍的JS坑19位Number精度损失问题的详细讲解和整合,希望对大家有所帮助。如果你有任何问题,请给我留言,边肖会及时回复你。非常感谢您对我们网站的支持!
版权声明:JS坑19位数字精度损失详解是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。