真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

JS大坑之19位數(shù)的Number型精度丟失問題詳解

More

創(chuàng)新互聯(lián)主要從事做網(wǎng)站、成都做網(wǎng)站、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)麟游,10年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18982081108

本項(xiàng)目僅供爬取體驗(yàn),每次訪問都會實(shí)時(shí)爬取數(shù)據(jù),所以數(shù)據(jù)返回速度會比較慢,實(shí)際操作應(yīng)該是定時(shí)爬取數(shù)據(jù)然后將數(shù)據(jù)存進(jìn)數(shù)據(jù)庫,數(shù)據(jù)從數(shù)據(jù)庫返回從而提高數(shù)據(jù)返回效率。

但項(xiàng)目很基礎(chǔ),可以作為以上各個(gè)node模塊最基礎(chǔ)的練手使用,希望可以幫到大家 😀起源

最近在實(shí)現(xiàn)一個(gè)需求的時(shí)候,需要接入第三方的接口,先調(diào)用A接口,A接口返回的數(shù)據(jù)里,有一個(gè)taskId,然后再使用這個(gè)taskId請求B接口,獲取最終需要的數(shù)據(jù)。

后端使用的是node,因此最開始使用的是request-promise這個(gè)包請求第三方接口,然而在獲取A接口返回的taskId之后,調(diào)用B接口之后,B接口的響應(yīng)居然是系統(tǒng)錯(cuò)誤!簡易代碼如下

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": "系統(tǒng)錯(cuò)誤",
//  "status": "failed"
// }

接著我使用postman請求A接口,獲取新的taskId,再用新的taskId請求B接口,結(jié)果卻是正常的!

我在反復(fù)檢查代碼,確認(rèn)請求的參數(shù)都是正常的格式之后,一時(shí)陷入了無盡的沉思之中。。。

發(fā)現(xiàn)

在做了幾次嘗試之后,我發(fā)現(xiàn)使用node請求得到的taskId最后兩位數(shù)都是0,即1152921504735848700,而使用postman獲取的taskId,則是比較正常的是1152921504735848759,接著我在node控制臺做如下操作

JS大坑之19位數(shù)的Number型精度丟失問題詳解

就是這么一瞬間,頓悟了。A接口里的taskId是個(gè)19位數(shù)字,而request-promise在將數(shù)據(jù)解析成json時(shí),導(dǎo)致這個(gè)19位的數(shù)字丟失了精度,查了下資料,發(fā)現(xiàn)js的number類型有個(gè)最大安全值,即2的53次方(9007199254740992),超過這個(gè)值就會出現(xiàn)精度丟失的問題。 Orz

獲取正確的響應(yīng)數(shù)據(jù)

由于在一開始使用request-promise包,因此獲取的taskId是丟失了精度了,因此改用了node原生的http模塊發(fā)送請求。

const req = https.request('https://xxx.com/A', (res) => {
  res.on('data', (chunk) => {
  // 由于這里獲取到的響應(yīng)數(shù)據(jù)是JSON字符串,因此19位的數(shù)字只是字符串的一部分,這時(shí)獲取到的taskId就是正確的數(shù)字
   console.log(`BODY: ${chunk}`);
  });
  res.on('end', () => {
   console.log('No more data in response.');
  })
 })

雖然獲取到了正常的響應(yīng)數(shù)據(jù),但是這是個(gè)JSON字符串,接下來還要把這個(gè)字符串解析成JSON,但是用JSON.parse(),又會引起精度丟失的問題,這可真尷尬 Orz

如果這個(gè)接口是已方可控的,那么就可以把這個(gè)19位數(shù)的number轉(zhuǎn)成字符串,這樣在解析的時(shí)候就不會出錯(cuò)了,但是由于是第三方接口,因此沒法改變。那么最快的解決方案,就是換種編程語言請求啊╮(╯_╰)╭

最后的解決

好吧,最后還是用了node,不過我用了比較硬核的方案實(shí)現(xiàn),先在獲取的JSON字符串中,找到這個(gè)19位的數(shù)字,然后為它加上引號,這樣再用JSON.parse()解析的時(shí)候,就能保持正常的數(shù)值,這樣接下的流程就自然通了,代碼如下

let result = '{"taskId":1152921504735848759,"status":"CREATED","progress":0.0,"success":true}'
// JSON.parse(result) 不為19位數(shù)補(bǔ)上雙引號,直接parse時(shí),精度丟失,結(jié)果如下:
// { 
//  taskId: 1152921504735848700,
//  status: 'CREATED',
//  progress: 0,
//  success: true 
// }
const taskId = result.match(/[0-9]{19}/)[0] // 正則獲取19位數(shù)字的值
result = result.replace(taskId,`"${taskId}"`) // 補(bǔ)上雙引號
const data = JSON.parse(result) 
// { 
//  taskId: '1152921504735848759', // 解析出來之后是字符串,因此沒有丟失精度
//  status: 'CREATED',
//  progress: 0,
//  success: true 
// }

結(jié)語

使用node也有一段時(shí)間了,因?yàn)樯婕安坏酱髷?shù)計(jì)算,因此對于編號啊,ID啊,都是用字符串形式進(jìn)行存儲的,也就一直沒有遇到這個(gè)問題。這一次居然碰上了,不得不說js在這一方面確實(shí)有點(diǎn)弱勢,之后也嘗試了下使用Go,python進(jìn)行請求,都是能正確解析不過node使用起來還是很舒服的

以上所述是小編給大家介紹的JS大坑之19位數(shù)的Number型精度丟失問題詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對創(chuàng)新互聯(lián)網(wǎng)站的支持!


當(dāng)前名稱:JS大坑之19位數(shù)的Number型精度丟失問題詳解
本文路徑:http://weahome.cn/article/pjjcoi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部