记开发中遇到的两个js最大安全值问题

2,002 阅读3分钟

最近开发过程中发现有两种case都是因为js精度导致的问题,记录一下~

Case 1:后端要求前端对某个值限制最大long型

后端大大说线上发现一种报错case,用户输入的id超过了Java Long型最大值,因为Long类型解析异常,直接返回系统异常。后端大大希望前端能加个校验,对输入的id进行下判断,超过Long型最大值时提示下输入的id不合法,能优化用户体验。

不得不说这个要求很合理,我没有拒绝的理由。好吧,代码撸起来。我设想的是就是封一个函数,入参是个字符串数字,我判断下这个值是否超过Long型最大值。写完之后在控制台进行试验。

咦,为啥有几个预期返回true的却返回的false,百度之后发现是因为超过js最大安全值时出现精度丢失的问题。 再改造一波代码:

Case 2: 后端返回的数字超过js最大安全值

事情是这样的,在某页面提交了一个模板保存成功之后跳转到我这边的详情页时url中带着某个id参数,我这边需要调后端A的接口去拿到这个模板的数据(后端A其实调的是B的接口,后端A在此时只是充当了转发角色)。在页面点击提交时,我把url中的这个参数给传给了后端A,提交成功之后回到了列表页,此时进入详情页再获取模板数据时发现后端A接口提示该id数据不存在。常规操作就是截图入参给后端A让他看下啥情况,此时后端B说这个id确实不在数据库里面。 纳尼,既然来到我这边详情页就代表这个数据是已经存在了,为啥会不在数据库里面,不行,我要找证据证明我这个id是有效的。

好咯,从头开始创建,打开控制台,开启Presever log,上传模板,点击保存,来到详情页,点击提交,看下入参,没问题,就是url中的这个id。好哒,来到列表页了,看下后端返回的数据,What!!!,这个id咋么和我创建时候传的不一样,啊啊啊,我好像找到真凶了,这看起来就是后端的锅,开森~~~截图下列表返回值和创建时的入参丢到群里,艾特下可爱的后端A。

有人会问,为啥你创建的时候这个值显示的是正常的,哈哈哈,因为我创建的时候传的是字符串,后端存数据库的时候存的是long型数字,所以在列表页我拿到的这个id数字其实已经超过js最大安全值了,出现了精度丢失。

此时不得不说一下js的最大安全值(2的53次方减1),即即9007199254740992,这个值有16位,当超过这个值时,就会出现精度丢失问题

这个事情最终的处理方案就是:后端将该id的数据类型改成string。

第一次掘金发文 and 六点半的起床的一天,今年的目标里有一项是希望能写一些文章,不管内容多少,难度如何,一步步走下去,相信能变好的