58 lines
1.5 KiB
JavaScript
58 lines
1.5 KiB
JavaScript
function Snowflake() {
|
|
this.epoch = 1698796800000 // 自定义起始时间(毫秒)
|
|
this.machineId = 1 // 固定 machineId
|
|
this.sequence = 0
|
|
this.lastTimestamp = -1
|
|
|
|
this.sequenceBits = 12
|
|
this.machineBits = 10
|
|
this.maxSequence = 2 ** this.sequenceBits - 1 // 4095
|
|
}
|
|
|
|
// 获取当前时间(毫秒)
|
|
Snowflake.prototype.currentTime = function () {
|
|
return Date.now()
|
|
}
|
|
|
|
// 等待下一毫秒
|
|
Snowflake.prototype.waitNextMillisecond = function (lastTimestamp) {
|
|
let timestamp = this.currentTime()
|
|
while (timestamp <= lastTimestamp) {
|
|
timestamp = this.currentTime()
|
|
}
|
|
return timestamp
|
|
}
|
|
|
|
// 生成 BigInt ID
|
|
Snowflake.prototype.nextId = function () {
|
|
let timestamp = this.currentTime()
|
|
|
|
if (timestamp < this.lastTimestamp) {
|
|
throw new Error('Clock moved backwards. Refusing to generate id.')
|
|
}
|
|
|
|
if (timestamp === this.lastTimestamp) {
|
|
this.sequence = (this.sequence + 1) & this.maxSequence
|
|
if (this.sequence === 0) {
|
|
timestamp = this.waitNextMillisecond(this.lastTimestamp)
|
|
}
|
|
}
|
|
else {
|
|
this.sequence = 0
|
|
}
|
|
|
|
this.lastTimestamp = timestamp
|
|
|
|
const id
|
|
= (BigInt(timestamp - this.epoch) << BigInt(this.machineBits + this.sequenceBits))
|
|
| (BigInt(this.machineId) << BigInt(this.sequenceBits))
|
|
| BigInt(this.sequence)
|
|
|
|
return id
|
|
}
|
|
|
|
// 返回固定长度字符串 ID(适合数据库存储)
|
|
Snowflake.prototype.nextIdStr = function (padLength = 20) {
|
|
return this.nextId().toString().padStart(padLength, '0')
|
|
}
|