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型精度丢失问题详解 的相关文章

  • 由于 apollo-client 未定义,无法解构 GraphQL 查询?

    我正在寻找调试与错误消息相关的问题 未捕获的类型错误 无法解构 0 apollo client WEBPACK IMPORTED MODULE 4 useQuery 因为它未定义 Context 我正在为我的 React js 项目设置后端
  • Javascript 函数查找数字的倍数

    创建一个名为的函数multiplesOf 它将接受两个参数 第一个参数是数字数组 第二个参数是数字 该函数应返回一个新数组 该数组由参数数组中的每个数字组成 该数字是参数数字的倍数 So multiplesOf 5 6 7 8 9 10 3
  • Eslint errorring 导入没有扩展名的 jsx

    我正在尝试在 es6 中导入 jsx 文件而不需要 jsx 扩展名 import LoginErrorDialog from LoginErrorDialogView Not import LoginErrorDialog from Log
  • 如何在react-bootstrap中禁用表单提交的

    在下面的代码片段中 我有许多文本类型的输入表单 如果用户点击 我似乎会得到相同的合成事件 就像他们按下提交按钮一样 我想忽略作为表单提交 只允许一个人按下 提交 按钮 我删除了一些表单组以减少示例 在所有情况下 按钮或 ENTER 键 e
  • 如何更改 Google Maps v3 API for Directions 中的开始和结束标记图像

    我使用 DirectionsRender 绘制了一条路线 但我不知道如何用我自己的标记替换通用的 Google 标记 我知道并在正常的谷歌地图情况下使用它 但发现很难用开始和结束的方向标记来做到这一点 如果这是一个愚蠢的问题 感谢您的任何建
  • 如何格式化 Highcharts 的 (x,y) 对数据的日期时间

    我的序列化方法会产生如下所示的日期时间字符串 2014 07 09T12 30 41Z 为什么下面的代码不起作用 function container highcharts xAxis type datetime series data x
  • 带有淘汰赛js的隐形recaptcha

    我正在完成隐形验证码 但我在实现它时遇到问题 谷歌开发人员页面中的代码显示它应该是这样的
  • 使用 dc.js 按条形值对条形图中的条形进行排序(排序)

    如何通过维度的计算值而不是维度本身的名称对 dc js 示例中的 x 轴 维度 进行排序 例如 请考虑序数条形图的 dc js 示例 https github com dc js dc js blob master web examples
  • Snap.svg - 停止在可悬停元素的子元素上重新触发悬停事件

    对于一个项目 我使用的 SVG 形状由背景多边形和背景多边形上方的一些文本 我已将其转换为路径 组成 我正在使用 Snap svg 为我的形状设置动画 当我将鼠标悬停在多边形上时 形状应该缩放到特定尺寸 包括其中的所有内容 鼠标移开时 形状
  • 防止 iOS 键盘在 cordova 3.5 中滚动页面

    我正在使用 Cordova 3 5 和 jQuery mobile 构建 iOS 应用程序 我在大部分应用程序中禁用了滚动功能 但是 当我选择输入字段时 iOS 键盘会打开并向上滚动页面 我不想要这个功能 由于输入足够高 键盘不会覆盖它 我
  • 如何将函数附加到弹出窗口关闭事件(Twitter Bootstrap)

    我做了一些搜索 但我只能认为我可以将事件附加到导致其关闭的按钮 https stackoverflow com questions 13205103 attach event handler to button in twitter boo
  • Angular - CSS - 自定义类型=文件输入,如何使用按钮而不是标签?

    我制作了一个类型为 file 的自定义输入字段 因为我不喜欢默认的输入字段 为了实现这一目标 我做了
  • 在 HTML5 画布中,如何用我选择的背景遮盖图像?

    我试图用画布来实现这一点 globalCompositeOperation 但没有运气 所以我在这里问 这里有类似的问题 但我没有在其中找到我的案例 我的画布区域中有图层 从下到上的绘制顺序 画布底座填充纯白色 fff 用fillRect
  • window.location 和 location.href 之间的区别

    我对之间的区别感到困惑window location and location href 两者似乎都以相同的方式行事 有什么不同 window location是一个对象 它保存有关当前文档位置的所有信息 主机 href 端口 协议等 lo
  • 可以设置标题样式吗? (并且使用CSS或js?)[重复]

    这个问题在这里已经有答案了 我想知道是否可以设计一个title a href title This is a title Hello a 样式问题有两个方面 文本格式 编码 我猜这是可能的 所以在问题中这样做 工具提示样式 你能把它弄大一点
  • 使用 Vue 的多模式组件

    我在 Vue 中实现动态模式组件时遇到问题 A common approach I follow to display a set of data fetched from the db is I dump each of the rows
  • 带参数的事件监听器

    我想将参数传递给 JavaScript 中的事件侦听器 我已经找到了解决方案 但我无法理解它们为什么或如何工作以及为什么其他解决方案不起作用 我有 C C 背景 但是 Javascript 函数的执行有很大不同 您能否帮助我理解以下示例如何
  • JavaScript 相对路径

    在第一个 html 文件中 我使用了一个变量类别链接 var categoryLinks Career prospects http localhost Landa DirectManagers 511 HelenaChechik Dim0
  • 如何在执行新操作时取消先前操作的执行?

    我有一个动作创建器 它会进行昂贵的计算 并在每次用户输入内容时调度一个动作 基本上是实时更新 但是 如果用户输入多个内容 我不希望之前昂贵的计算完全运行 理想情况下 我希望能够取消执行先前的计算并只执行当前的计算 没有内置功能可以取消Pro
  • Vue.js[vuex] 如何从突变中调度?

    我有一个要应用于 json 对象的过滤器列表 我的突变看起来像这样 const mutations setStars state payload state stars payload this dispatch filter setRev

随机推荐

  • 【生产篇】_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