JS大坑之19位数的Number型精度丢失问题详解

2023-11-04

这篇文章主要介绍了JS大坑之19位数的Number型精度丢失问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,有兴趣的朋友们可以一起来学习探讨。

最近在实现一个需求的时候,需要接入第三方的接口,先调用A接口,A接口返回的数据里,有一个taskId,然后再使用这个taskId请求B接口,获取最终需要的数据。

后端使用的是node,因此最开始使用的是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) 
// {
//  "errorcode": "40001",
//  "message": "系统错误",
//  "status": "failed"
// }

接着我使用postman请求A接口,获取新的taskId,再用新的taskId请求B接口,结果却是正常的!

我在反复检查代码,确认请求的参数都是正常的格式之后,一时陷入了无尽的沉思之中……

发现 

在做了几次尝试之后,我发现使用node请求得到的taskId最后两位数都是0,即1152921504735848700,而使用postman获取的taskId,则是比较正常的是1152921504735848759,接着我在node控制台做如下操作:

就是这么一瞬间,顿悟了。A接口里的taskId是个19位数字,而request-promise在将数据解析成json时,导致这个19位的数字丢失了精度,查了下资料,发现js的number类型有个最大安全值,即2的53次方(9007199254740992),超过这个值就会出现精度丢失的问题。

获取正确的响应数据 

由于在一开始使用request-promise包,因此获取的taskId是丢失了精度了,因此改用了node原生的http模块发送请求。

const req = https.request('https://xxx.com/A', (res) => {
  res.on('data', (chunk) => {
  // 由于这里获取到的响应数据是JSON字符串,因此19位的数字只是字符串的一部分,这时获取到的taskId就是正确的数字
   console.log(`BODY: ${chunk}`);
  });
  res.on('end', () => {
   console.log('No more data in response.');
  })
 })

虽然获取到了正常的响应数据,但是这是个JSON字符串,接下来还要把这个字符串解析成JSON,但是用JSON.parse(),又会引起精度丢失的问题,这可真尴尬 ……

如果这个接口是已方可控的,那么就可以把这个19位数的number转成字符串,这样在解析的时候就不会出错了,但是由于是第三方接口,因此没法改变。那么最快的解决方案,就是换种编程语言请求啊。

最后的解决

好吧,最后还是用了node,不过我用了比较硬核的方案实现,先在获取的JSON字符串中,找到这个19位的数字,然后为它加上引号,这样再用JSON.parse()解析的时候,就能保持正常的数值,这样接下的流程就自然通了,代码如下:

let result = '{"taskId":1152921504735848759,"status":"CREATED","progress":0.0,"success":true}'
// JSON.parse(result) 不为19位数补上双引号,直接parse时,精度丢失,结果如下:
// { 
//  taskId: 1152921504735848700,
//  status: 'CREATED',
//  progress: 0,
//  success: true 
// }
const taskId = result.match(/[0-9]{19}/)[0] // 正则获取19位数字的值
result = result.replace(taskId,`"${taskId}"`) // 补上双引号
const data = JSON.parse(result) 
// { 
//  taskId: '1152921504735848759', // 解析出来之后是字符串,因此没有丢失精度
//  status: 'CREATED',
//  progress: 0,
//  success: true 
// }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JS大坑之19位数的Number型精度丢失问题详解 的相关文章

  • 禁用内容安全策略

    当我开发网站时 我经常想看看特定功能在网站上的外观如何 所以我会使用 chrome 开发者工具并经常运行一些 javascript 脚本 我经常发现一些脚本由于内容安全策略 CSP 而无法运行的问题 我完全理解该策略是为了防止跨站点脚本攻击
  • 我如何在 AngularJS 中监听点击并按住的情况?

    我制作了一个时间计数器 您可以通过单击按钮来增加或减少时间 然而 我希望当我单击并按住按钮时 时间的价值会不断攀升 所以目前如果你看到我的Plunkr http plnkr co edit BxX9x5zYFMXVqt5JsN1F p pr
  • chrome 调试器承诺在暂停时不会解析?

    也许我没有正确调试承诺 但基本上 如果您在断点处停止并运行异步代码 它实际上不会完成 直到您恢复执行为止 这是一个问题 调试器允许您快速试验多个 api 方法 但如果您恢复它 您就不能 debugger now type the follo
  • 如何通过单击图像预览上的“x”从文件输入中删除图像?

    我目前有一个文件输入 一旦用户上传图像 就会显示图像预览 在图像预览上 有一个 x 可以从列表中删除图像预览 单击此 x 后 有什么方法可以从输入中的文件集中删除图像吗
  • 如果对象包含在另一个数组中,则从数组中删除该对象

    我试图从数组中删除一个对象 如果该对象的属性 唯一 包含在另一个数组中 我知道我可以像这样执行嵌套 for 循环 for i 0 i lt array length i for j 0 j lt array2 length j if arr
  • 取消html5浏览器中的单图请求

    我正在动态加载 大 图像以绘制到 html5 画布中 如下所示 var t new Image t onload t src http myurl 但每隔一段时间就会想取消图片请求完全地 我想出的唯一方法是设置src to i e t sr
  • HTML/VBA Click 事件未触发

    这是我第一次在 StackOverflow 上发布问题 到目前为止 我已经能够通过 VBA 帮助论坛解决我的大部分问题 我的问题很简单 我有一个自动数据拉取 我需要在其中导出数据 我过去曾在这方面取得过成功 但这次略有不同 我尝试单击以生成
  • Jquery从下拉列表中获取所选值的id

    我有一个下拉列表 可以从数据库获取值 如下所示 get getJobs function jobs seljobs jobs var i 0 jobs forEach function n alert job id n id 32 67 4
  • jQuery 选择 # id 以单词为前缀,计数器为后缀

    有没有办法用 jQuery 选择所有带有前缀 my 和后缀 0 9 的 id 像这样的 my 1 4 还是可以用循环来实现 div div div div div div div div div div 第一个想法 似乎效果很好 div i
  • 如何仅在 NextJS 站点构建期间使用 getInitialProps?

    当使用 NextJS 构建静态站点时 我想要getInitialProps方法仅在构建步骤期间触发 而不是在客户端上触发 在构建步骤中 NextJS 运行getInitialProps 方法 https nextjs org docs fe
  • 淡出和循环一组 div 的最佳方式

    假设我有以下 div div class a You are funny div div class b You are smart div div class c You are cool div 最好的展示方式是什么div a持续 5
  • 为什么“tbody”不设置表格的背景颜色?

    我在用 tbody 作为 CSS 选择器来设置background color在一个表中 我这样做是因为我有多个 tbody 表内的部分 它们具有不同的背景颜色 我的问题是 当使用border radius在细胞上 细胞不尊重backgro
  • 如何在jquery中获取保存时间和当前时间的差异?

    我想在 javascript 或 jquery 中获取保存时间和当前时间之间的时差 我节省的时间看起来像Sun Oct 24 15 55 56 GMT 05 30 2010 java中的日期格式代码如下 String newDate 201
  • Nodejs mysql 获取正确的时间戳格式

    我在用着mysqljs https github com mysqljs mysql得到结果后sql我变得不同TimeStamp格式如下 created at Sat Jul 16 2016 23 52 54 GMT 0430 IRDT 但
  • 如何获取 UIWebView 中元素的位置?

    我在 iPad 程序中加载了 html 的 UIWebView 通过使用 webkit column width 我将 html 分为几列 padding 0px height 1024px webkit column gap 0px we
  • 无法在前端使用 JavaScript Fetch API 将文件上传到 FastAPI 后端

    我正在尝试弄清楚如何将图像发送到我的 API 并验证生成的token那是在header的请求 到目前为止 这就是我所处的位置 app post endreProfilbilde async def endreProfilbilde requ
  • 如何在 javascript 正则表达式中匹配平衡分隔符?

    我原以为这个问题是不可能的 据我所知 Javascript 的正则表达式既没有递归插值 也没有漂亮的 NET 平衡组功能 但问题就在那里 如问题 12 所示正则表达式 alf nu http regex alf nu 匹配平衡对 lt an
  • 在 Javascript 中减少/分组数组

    基于this https stackoverflow com a 40774906 3254598例如 我想以稍微不同的方式按对象进行分组 结果应该如下 key audi items make audi model r8 year 2012
  • 如何在打字稿文件中导入没有定义文件的js库

    随着我们的项目变得越来越大 我想从 JavaScript 切换到 TypeScript 以帮助进行代码管理 然而 我们使用许多库作为 amd 模块 我们不想将其转换为 TypeScript 我们仍然想将它们导入 TypeScript 文件
  • KeyboardAvoidingView - 隐藏键盘时重置高度

    我正在使用 React NativeKeyboardAvoidingView设置我的高度View当显示键盘时 但是当我关闭应用程序中的键盘时 视图的高度不会变回原来的值

随机推荐

  • 【生产篇】_Oracle ADG同步技术 ——DBA必备的一种“后悔药”

    note taker Ethan Yang recording time 2019 09 23 number of docs 11 引言 所有高可用性方案的本质就是 冗余 当然预算开支也会随着高可用性要求的提升而变得异常昂贵 大家在构建数据
  • 配置apache2.4.46虚拟目录

    配置虚拟目录 修改httpd conf 定位IfModule alias module这个模块 在 Alias webpath full filesystem path下按照格式改写 在模块末尾 lt Ifmodule gt 的上面加一段
  • Markdown编辑器【Typora 1.5.10】免费版下载、安装教程(亲测有效!!!)

    文章涉及Markdown版本为1 5 10 一 简介 1 Typora是一款非常好用的 Markdown 编辑器和阅读器 2 支持实时预览的轻量级 Markdown 编辑器 二 安装包及所涉及插件下载 阿里云盘 https www aliy
  • 测试面试LeetCode系列:一维数组的动态和

    每日一刷的LeetCode题目又来了 寒冬之下 助你拿一个大厂的测开offer 给你一个数组 nums 数组 动态和 的计算公式为 runningSum i sum nums 0 nums i 请返回 nums 的动态和 示例 1 输入 n
  • Qualcomm AR SDK之替换模型(已解决模型贴图问题)

    ARVR技术交流群 129340649 欢迎加入 求从事移动应用开发以及基于移动终端的AR应用开发的朋友 一起做一些事 有兴趣可以给我私信 谢谢 1 将模型转换为 obj格式 这个通过很多三维软件都可以实现 我用的是3Dmax 2 将obj
  • Flutter上你需要一个简单实用的验证码输入Widget

    现在很多app都有填写验证码的需求 而这个验证码的UI流行非普通的输入框 毕竟移动开发主要矛盾是设计师日益增长的天马行空同落后的开发之间的矛盾 作为跨平台方案的Flutter自然也会用到这种控件 本着少造轮子 多copy的原则 想去找个验证
  • 《Python进阶系列》六:Python中的文件对象

    文件对象的seek 和tell 打开一个文件 读取内容 是很常见的操作 不过有的时候我们还需要反复读取文件中的内容 如果多次打开文件读取再多次关闭 显然不是特别好的操作 我们可以借助Python文件对象的seek 和tell 函数 来实现反
  • 为什么那么多人用小智ai

    ChatGPT丨小智ai丨chatgpt丨人工智能丨OpenAI丨聊天机器人丨AI语音助手丨GPT 3 5丨OpenAI ChatGPT GPT 4 GPT 3 人机对话 ChatGPT应用 小智ai 小智ai 小智ai 小智ai Chat
  • Shader理论(2):Unity中的各种坐标系

    目录 前言 一 坐标系 1 1 世界坐标系 World Space 1 2 本地坐标系 Local Space 模型坐标系 1 3 屏幕坐标系 Screen Space 1 4 观察坐标系 ViewPort Space 视口坐标系 1 5
  • 如何设计一个短信发送功能

    本文主要分享了如何设计一个发送短信功能 一 总结简述 1 梳理多个平台短信API的发送参数 集成封装提供统一的API 支持多个短信平台 阿里云 腾讯云 百度云 京东云 七牛云 灵活切换 2 提供存储方案 表结构设计 3 提供真实生产项目代码
  • 内核配置中的:Multifunction device drivers

    Multifunction Device Drivers 多功能设备Linux下驱动开发 先来一个英文简介 Multifunction devices embed several functions e g GPIOs touchscree
  • kafka的一些基本命令

    kafka brokers test 8090 zookeeper servers test 2181 1 查看test服务器中的所有topic bin kafka topics sh list zookeeper test 2181 2
  • stable diffusion(Lora的训练)

    以坤坤为例 上网随便找了几个坤坤的人脸图像 作为训练的数据集 1 训练环境搭建 建议看一遍教程 虽然这个up主好像不是很专业的样子 不过流程差不多是这样的 重点关注一下虚拟环境搭建完之后 在终端选择配置的操作 就是一堆yes no 的选项
  • 国产麒麟系统KylinOS Server V10 SP2安装MongoDB6.0版本

    1 下载安装包 安装下载链接 https fastdl mongodb org linux mongodb linux aarch64 rhel82 6 0 6 tgz 2 上传到服务器 3 解压安装包 tar zxvf mongodb l
  • AF Http request 代理形式回调

    AF是以block的方式将请求结果返回 这样的处理思路我感觉很好 每个请求都单独处理自己的回调 AF的请求也可以使代理的形式进行回调 HIHTTPRequest 以代理的形式回调的话需要创建一个请求类 然后将请求结果以代理的形式回调 HIH
  • 毕业论文参考文献格式设置(以GB/T 7714-2015为例)

    Ref https zhuanlan zhihu com p 376138185 下载链接 https www endnote com style download chinese standard gb t7714 numeric 链接
  • 四路服务器选型项目,四路服务器详细

    四路服务器详细 内容精选 换一换 弹性云服务器 Elastic Cloud Server 是一种可随时自动获取 计算能力可弹性伸缩的云服务器 可帮助您打造可靠 安全 灵活 高效的应用环境 确保服务持久稳定运行 提升运维效率 本节介绍REST
  • 【Unity】UnityのTimelineが実機で再生されない件について

    Unity Unity Timeline 実機 再生 件 https qiita com hide gugen items 7fee18be2c789144ed74 経緯 Editor上 普通 再生 日AssetBundle化 iPhone
  • 华为隐藏功能扩大内存代码大全_华为手机绝密功能,在拨号界面就能揭开

    你知道吗 华为手机里的那些隐藏功能 打开方式居然是 拨号界面 只要在拨号界面输入指定代码 就会自动弹出隐藏功能 今天我就来给大家科普科普 那些隐藏在华为手机里的代码大全 测试代码 虽然这个代码叫测试代码 但对咱们普通用户来说却是一个非常实用
  • JS大坑之19位数的Number型精度丢失问题详解

    这篇文章主要介绍了JS大坑之19位数的Number型精度丢失问题 文中通过示例代码介绍的非常详细 对大家的学习或者工作具有一定的参考学习价值 有兴趣的朋友们可以一起来学习探讨 最近在实现一个需求的时候 需要接入第三方的接口 先调用A接口 A