1、先看现象
第三条记录由于员工接口仅能查询在职员工,历史信息无法返回。这里做了兼容处理,直接展示账号id。
但用这个id去数据库里面查询返回的结果如下:
居然查询不到,这个表里面是所有员工的账号信息,包括离职员工的。
2、原因分析
那么先确定代码有没有问题,既然在职员工能正常返回。说明代码逻辑应该没有问题的。那么这个记录的创建人的id到底是不是这个值呢。 我们这个id是通过雪花算法生产的,具体的生成代码逻辑如下:
/**
* 获得下一个ID (该方法是线程安全的)
*
* @return SnowflakeId
*/
public synchronized long nextId() {
long timestamp = timeGen();
//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
if (timestamp < lastTimestamp) {
throw new RuntimeException(
String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
//如果是同一时间生成的,则进行毫秒内序列
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
//毫秒内序列溢出
if (sequence == 0) {
//阻塞到下一个毫秒,获得新的时间戳
timestamp = tilNextMillis(lastTimestamp);
}
}
//时间戳改变,毫秒内序列重置
else {
sequence = 0L;
}
//上次生成ID的时间截
lastTimestamp = timestamp;
//移位并通过或运算拼到一起组成64位的ID
return ((timestamp - twepoch) << timestampLeftShift)
| (dataCenterId << dataCenterIdShift)
| (workerId << workerIdShift)
| sequence;
}
它生成的id都是比较长的。
2.1、真实值
我们把这个接口的返回值仔细分析一下:
{
"creator": 1342811569921765378,
"gmtCreate": "2024-04-02 14:46:12",
"gmtModify": "2024-04-02 14:46:15",
"deleteBranchFlag": 0
}
看到接口里面返回的居然是 1342811569921765378,这个就有点意外了。
2.2、JavaScript对long型数字处理的失真
这里能明显看到在转换为数字的时候失真了。
到底在JavaScript中能够表达的最大数字是多少呢,查询官方资料得到如下结果。developer.mozilla.org/zh-CN/docs/… 它能表达的最大数字是9007199254740991。如果超过它需要使用bigInt。
2.3、哪一步失真的?
接口返回结果里面的值是正确的,而且都是用字符串格式返回。由于返回的格式是Json。
return efetch(holeUrl, requestInit).then(
(response) => {
let json = response.json();
let status = response.status;
// 登录态失效,返回登录页面
if(status === 417 || status === 418){
logout();
}
return json;
}
);
这里response.json()直接返回了Json对象,在这一步就出现了失真。
3、如何解决
这个记得以前处理订单编号也出现同样的现象。Java的Long对象的精度比js的高。彻底解决,就是对这种超长的数字,返回模型直接处理为字符串。避免由parse过程出现失真。
{
"creator": "1342811569921765378",
"gmtCreate": "2024-04-02 14:46:12",
"gmtModify": "2024-04-02 14:46:15",
"deleteBranchFlag": 0
}
如上格式即可解决。