json-bigint的介紹和使用-解決Javascript的有關大整數問題

JavaScript 能夠準確表示的整數範圍在-2^53到 2^53之間(不含兩個端點),超過這個範圍,無法精確表示這個值,這使得 JavaScript 不適合進行科學和金融方面的精確計算。

先舉個例子

Math.pow(2, 53) // 9007199254740992

9007199254740992  // 9007199254740992
9007199254740993  // 9007199254740992

Math.pow(2, 53) === Math.pow(2, 53) + 1
// true

上面代碼中,超出 2 的 53 次方之後,一個數就不精確了。

ES6 引入了Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER這兩個常量,用來表示這個範圍的上下限。

Number.MAX_SAFE_INTEGER === Math.pow(2, 53) - 1
// true
Number.MAX_SAFE_INTEGER === 9007199254740991
// true

Number.MIN_SAFE_INTEGER === -Number.MAX_SAFE_INTEGER
// true
Number.MIN_SAFE_INTEGER === -9007199254740991
// true

上面代碼中,可以看到 JavaScript 能夠精確表示的極限。

後端返回的數據一般都是 JSON 格式的字符串。

'{ "id": 9007199254740995, "name": "Jack", "age": 18 }'

如果這個字符不做任何處理,你能方便的獲取到字符串中的指定數據嗎?非常麻煩。所以我們要把它轉換爲 JavaScript 對象來使用就很方便了。

幸運的是 axios 爲了方便我們使用數據,它會在內部使用 JSON.parse() 把後端返回的數據轉爲 JavaScript 對象。

// { id: 9007199254740996, name: 'Jack', age: 18 }
JSON.parse('{ "id": 9007199254740995, "name": "Jack", "age": 18 }')

可以看到,超出安全整數範圍的 id 無法精確表示,這個問題並不是 axios 的錯。

瞭解了什麼是大整數的概念,接下來的問題是如何解決?

json-bigint 是一個第三方包,它可以幫我們很好的處理這個問題。

使用它的第一步就是把它安裝到你的項目中。

npm i json-bigint

下面是使用它的一個簡單示例。

const jsonStr = '{ "art_id": 1245953273786007552 }'

console.log(JSON.parse(jsonStr)) // 1245953273786007600
// JSON.stringify()

// JSONBig 可以處理數據中超出 JavaScript 安全整數範圍的問題
console.log(JSONBig.parse(jsonStr)) // 把 JSON 格式的字符串轉爲 JavaScript 對象

// 使用的時候需要把 BigNumber 類型的數據轉爲字符串來使用
console.log(JSONBig.parse(jsonStr).art_id.toString()) // 1245953273786007552

console.log(JSON.stringify(JSONBig.parse(jsonStr)))

console.log(JSONBig.stringify(JSONBig.parse(jsonStr))) // 把 JavaScript 對象 轉爲 JSON 格式的字符串轉

 

 

json-bigint 會把超出 JS 安全整數範圍的數字轉爲一個 BigNumber 類型的對象,對象數據是它內部的一個算法處理之後的,我們要做的就是在使用的時候轉爲字符串來使用。

解決方法:(案例)
通過 Axios 請求得到的數據都是 Axios 處理(JSON.parse)之後的,我們應該在 Axios 執行處理之前手動使用 json-bigint 來解析處理。Axios 提供了自定義處理原始後端返回數據的 API:transformResponse 。

import axios from 'axios'

import jsonBig from 'json-bigint'

var json = '{ "value" : 9223372036854775807, "v2": 123 }'

console.log(jsonBig.parse(json))

const request = axios.create({
  baseURL: '你接口的基礎路徑', // 接口基礎路徑

  // transformResponse 允許自定義原始的響應數據(字符串)
  transformResponse: [function (data) {
    try {
      // 如果轉換成功則返回轉換的數據結果
      return jsonBig.parse(data)
    } catch (err) {
      // 如果轉換失敗,則包裝爲統一數據格式並返回
      return {
        data
      }
    }
  }]
})

export default request

更多內容請參見:

https://www.teqng.com/2021/07/29/node-js-%E4%B8%AD%E9%81%87%E5%88%B0%E5%A4%A7%E6%95%B0%E5%A4%84%E7%90%86%E7%B2%BE%E5%BA%A6%E4%B8%A2%E5%A4%B1%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3%EF%BC%9F/#JavaScript_zui_da_an_quan_zheng_shu






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章