The origin of

Recently, when implementing A requirement, we need to access the interface of A third party. First, we call interface A, and there is A taskId in the data returned by interface A. Then, we use this taskId to request interface B to obtain the data we finally need.

Node is used at the back end, so the request-Promise package was used to request the third-party interface at the beginning. However, after obtaining the taskId returned by interface A, interface B responded with A system error after calling interface B. The simple code is as follows

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": "system error"
// "status": "failed"
// }
Copy the code

Then I use postman to request interface A, get A new taskId, and use the new taskId to request interface B, but the result is normal!

After I double-checked the code to make sure that the parameters in the request were in the correct format, I lost myself in endless meditation…

found

After several attempts, I found that the last two digits of the taskId obtained by node request were all 0 (1152921504735848700), while the taskId obtained by postman request was normal (1152921504735848759). I then do the following on the Node console

That’s 2 to the 53. 9007199254740992

Get the correct response data

Since the request-Promise package was originally used, the taskId was lost in accuracy, so node’s native HTTP module was used instead to send the request.

const req = https.request('https://xxx.com/A', (res) => {
    res.on('data', (chunk) => {
    // Since the response data is a JSON string, the 19-digit number is only part of the string, and the taskId is the correct number
      console.log(`BODY: ${chunk}`);
    });
    res.on('end', () = > {console.log('No more data in response.'); })})Copy the code

Parse () will cause a loss of precision, which can be embarrassing Orz

If the interface were controlled, you could convert the 19-digit number to a string that would parse without error, but because it’s a third-party interface, you can’t change it. Well, the quickest solution would be to change languages

Final solution

Parse () : Node (); parse(); parse() : Node (); parse()

let result = '{" taskId ", 1152921504735848759, "status" : "CREATED", "progress" : 0.0, "success" : true}'
// json. parse(result) Does not fill 19 digits with double quotation marks.
/ / {
// taskId: 1152921504735848700,
// status: 'CREATED',
// progress: 0,
// success: true
// }
const taskId = result.match(/ [0-9] {19} /) [0] // The re gets the 19-digit value
result = result.replace(taskId,`"${taskId}"`) // add double quotes
const data = JSON.parse(result) 
/ / {
// taskId: '1152921504735848759', // it is a string, so there is no loss of precision
// status: 'CREATED',
// progress: 0,
// success: true
// }
Copy the code

conclusion

I have been using Node for a while now, because it does not involve large numbers, so the numbers and ids are stored in string form, so I have not encountered this problem. This time unexpectedly met, have to say that JS in this aspect is really a little weak, later also tried to use Go, Python request, are able to correctly parse. ┑( ̄  ̄)┍ but node is very comfortable to use, ╮(╯▽╰)╭

Thanks!