背景

  • BFF Client 应用的 npm 包 request-promise-native 申请微服务接口返回 ID 精度失落
1713166949059674112 => 1713166949059674000

为什么会失落?

  • 存储二进制时小数点的偏移量最大为52位,计算机存储的为二进制,而能存储的二进制为62位,超出就会有舍入操作,因而 JS 中能精准示意的最大整数是 Math.pow(2, 53),十进制即9007199254740992大于 9007199254740992 的可能会失落精度

    • 参考:https://zhuanlan.zhihu.com/p/...
  • request-promise-native 发动申请时,当options.json 不为 false 会应用 JSON.parse 解析 body
if (self._json) {  try {    response.body = JSON.parse(response.body, self._jsonReviver)  } catch (e) {    debug('invalid JSON received', self.uri.href)  }}

最小 demo

搭建服务 API

一、搭建 Java Web Api:

  • 参考:Building a RESTful Web Service
  • 批改 service 层使 id 最小值大于 js 精度限度
    public long getId() {        return id + 1713166949059674112L;    }* 批改 controller 层增加 post 申请    @PostMapping("/greeting_create")    public Greeting createGreeting(@RequestParam(value = "name", defaultValue = "World") String name) {        return new Greeting(counter.incrementAndGet(), String.format(template, name));    }

二、申请

  • GET 申请: curl http://localhost:8080/greeting
  • POST 申请:curl -X POST http://localhost:8080/greeting_create
{"id":1713166949059674120,"content":"Hello, World!"}

解决方案

1. 获取响应体的字符串,应用 JSONbigid 转化成字符串

  • 长处:只影响以后申请
  • 毛病:不反对 POST 申请形式,

    • 通过 json 传参数不反对
    • 通过 form + json: false 传参数须要后端接口反对
  • GET 申请
const rp = require('request-promise-native');const jsonBigInt = require('json-bigint');  const getOptions = {    'method': 'GET',    json: false,    'url': 'http://localhost:8080/greeting',  };  const getRes = await rp(getOptions);  console.log('get result: ', jsonBigInt.parse(getRes));
  • POST 申请:不反对,json 被占用,肯定会执行 JSON.parse
const rp = require('request-promise-native');const jsonBigInt = require('json-bigint');  const postOptions = {    'method': 'POST',    'url': 'http://localhost:8080/greeting_create',    json: { name: 'test' },  };  const postRes = await rp(postOptions);  console.log('post result: ', jsonBigInt.parse(postRes));

2. 应用 JSONbig.parse() 替换 JSON.parse()

  • 长处:实现简略,反对 POST
  • 毛病:影响所有的 JSON.parse() 解析
const rp = require('request-promise-native');const jsonBigInt = require('json-bigint');async function jsonBigReplaceParse() {  const oldParse = JSON.parse;  JSON.parse = jsonBigInt.parse;  const postOptions = {    'method': 'POST',    'url': 'http://localhost:8080/greeting_create',    json: { name: 'test' },  };  const postRes = await rp(postOptions);  console.log('post result: ', postRes);  JSON.parse = oldParse;}

~

~ 本文完,感激浏览!

~

学习乏味的常识,结识乏味的敌人,塑造乏味的灵魂!

大家好,我是〖编程三昧〗的作者 隐逸王,我的公众号是『编程三昧』,欢送关注,心愿大家多多指教!