Js Snowflake(雪花算法)生成隨機(jī)ID的實(shí)現(xiàn)方法
1、snowflake-id插件
import SnowflakeId from "snowflake-id";
const guid = num => {
const id= new SnowflakeId();
return id.generate();
};
2、原生使用
var Snowflake = /** @class */ (function() {
function Snowflake(_workerId, _dataCenterId, _sequence) {
this.twepoch = 1288834974657n;
//this.twepoch = 0n;
this.workerIdBits = 5n;
this.dataCenterIdBits = 5n;
this.maxWrokerId = -1n ^ (-1n << this.workerIdBits); // 值為:31
this.maxDataCenterId = -1n ^ (-1n << this.dataCenterIdBits); // 值為:31
this.sequenceBits = 12n;
this.workerIdShift = this.sequenceBits; // 值為:12
this.dataCenterIdShift = this.sequenceBits + this.workerIdBits; // 值為:17
this.timestampLeftShift = this.sequenceBits + this.workerIdBits + this.dataCenterIdBits; // 值為:22
this.sequenceMask = -1n ^ (-1n << this.sequenceBits); // 值為:4095
this.lastTimestamp = -1n;
//設(shè)置默認(rèn)值,從環(huán)境變量取
this.workerId = 1n;
this.dataCenterId = 1n;
this.sequence = 0n;
if(this.workerId > this.maxWrokerId || this.workerId < 0) {
thrownew Error('_workerId must max than 0 and small than maxWrokerId-[' + this.maxWrokerId + ']');
}
if(this.dataCenterId > this.maxDataCenterId || this.dataCenterId < 0) {
thrownew Error('_dataCenterId must max than 0 and small than maxDataCenterId-[' + this.maxDataCenterId + ']');
}
this.workerId = BigInt(_workerId);
this.dataCenterId = BigInt(_dataCenterId);
this.sequence = BigInt(_sequence);
}
Snowflake.prototype.tilNextMillis = function(lastTimestamp) {
var timestamp = this.timeGen();
while(timestamp <= lastTimestamp) {
timestamp = this.timeGen();
}
return BigInt(timestamp);
};
Snowflake.prototype.timeGen = function() {
return BigInt(Date.now());
};
Snowflake.prototype.nextId = function() {
var timestamp = this.timeGen();
if(timestamp < this.lastTimestamp) {
thrownew Error('Clock moved backwards. Refusing to generate id for ' +
(this.lastTimestamp - timestamp));
}
if(this.lastTimestamp === timestamp) {
this.sequence = (this.sequence + 1n) & this.sequenceMask;
if(this.sequence === 0n) {
timestamp = this.tilNextMillis(this.lastTimestamp);
}
} else {
this.sequence = 0n;
}
this.lastTimestamp = timestamp;
return((timestamp - this.twepoch) << this.timestampLeftShift) |
(this.dataCenterId << this.dataCenterIdShift) |
(this.workerId << this.workerIdShift) |
this.sequence;
};
return Snowflake;
}());
console.log(new Snowflake(1n, 1n, 0n).nextId());
//1141531990672150528n
控制臺(tái)輸出1141531990672150528n為bigint格式, .toString()轉(zhuǎn)為字符串格式即可
3、ES6使用
import bigInt from "big-integer";
const guid = () => {
const Snowflake = /** @class */ (function() {
function Snowflake(_workerId, _dataCenterId, _sequence) {
// this.twepoch = 1288834974657;
this.twepoch = 0;
this.workerIdBits = 5;
this.dataCenterIdBits = 5;
this.maxWrokerId = -1 ^ (-1 << this.workerIdBits); // 值為:31
this.maxDataCenterId = -1 ^ (-1 << this.dataCenterIdBits); // 值為:31
this.sequenceBits = 12;
this.workerIdShift = this.sequenceBits; // 值為:12
this.dataCenterIdShift = this.sequenceBits + this.workerIdBits; // 值為:17
this.timestampLeftShift = this.sequenceBits + this.workerIdBits + this.dataCenterIdBits; // 值為:22
this.sequenceMask = -1 ^ (-1 << this.sequenceBits); // 值為:4095
this.lastTimestamp = -1;
//設(shè)置默認(rèn)值,從環(huán)境變量取
this.workerId = 1;
this.dataCenterId = 1;
this.sequence = 0;
if (this.workerId > this.maxWrokerId || this.workerId < 0) {
throw new Error(
'config.worker_id must max than 0 and small than maxWrokerId-[' + this.maxWrokerId + ']'
);
}
if (this.dataCenterId > this.maxDataCenterId || this.dataCenterId < 0) {
throw new Error(
'config.data_center_id must max than 0 and small than maxDataCenterId-[' +
this.maxDataCenterId +
']'
);
}
this.workerId = _workerId;
this.dataCenterId = _dataCenterId;
this.sequence = _sequence;
}
Snowflake.prototype.tilNextMillis = function(lastTimestamp) {
var timestamp = this.timeGen();
while (timestamp <= lastTimestamp) {
timestamp = this.timeGen();
}
return timestamp;
};
Snowflake.prototype.timeGen = function() {
//new Date().getTime() === Date.now()
return Date.now();
};
Snowflake.prototype.nextId = function() {
var timestamp = this.timeGen();
if (timestamp < this.lastTimestamp) {
throw new Error(
'Clock moved backwards. Refusing to generate id for ' + (this.lastTimestamp - timestamp)
);
}
if (this.lastTimestamp === timestamp) {
this.sequence = (this.sequence + 1) & this.sequenceMask;
if (this.sequence === 0) {
timestamp = this.tilNextMillis(this.lastTimestamp);
}
} else {
this.sequence = 0;
}
this.lastTimestamp = timestamp;
var shiftNum =
(this.dataCenterId << this.dataCenterIdShift) |
(this.workerId << this.workerIdShift) |
this.sequence; // dataCenterId:1,workerId:1,sequence:0 shiftNum:135168
var nfirst = new bigInt(String(timestamp - this.twepoch), 10);
nfirst = nfirst.shiftLeft(this.timestampLeftShift);
var nnextId = nfirst.or(new bigInt(String(shiftNum), 10)).toString(10);
return nnextId;
};
return Snowflake;
})();
return new Snowflake(1, 1, 0).nextId();
};
guid()即可調(diào)用
4、多次重復(fù)調(diào)用出現(xiàn)一樣id的bug
console.log(guid(), new Date().getTime()); console.log(guid(), new Date().getTime()); console.log(guid(), new Date().getTime()); console.log(guid(), new Date().getTime()); console.log(guid(), new Date().getTime()); console.log(guid(), new Date().getTime()); console.log(guid(), new Date().getTime()); console.log(guid(), new Date().getTime()); console.log(guid(), new Date().getTime()); console.log(guid(), new Date().getTime()); console.log(guid(), new Date().getTime()); console.log(guid(), new Date().getTime());

修改如下
import SnowflakeId from "snowflake-id";
const guid = num => {
const snowflake = new SnowflakeId();
let arr = [];
for (let i = 0; i < num; i++) {
arr.push(snowflake.generate());
}
return num ? arr : snowflake.generate();
};
單個(gè)調(diào)用 guid()
n個(gè)調(diào)用 guid(n)
到此這篇關(guān)于Js Snowflake(雪花算法)生成隨機(jī)ID的實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)Js 雪花算法生成隨機(jī)ID內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談javascript的Array.prototype.slice.call
發(fā)現(xiàn)大多人都用了Array.prototype.slice.call(argments,0),一直不明白這句是干什么的。而昨天溫習(xí)了slice()方法,再參考Function.call(thisArg[, arg1[, arg2[, ...]]]),還是不得而知(我腦筋轉(zhuǎn)得慢:|)。2015-08-08
javascript 三組文字間隙滾動(dòng)實(shí)例代碼
非常實(shí)用的文字間隙滾動(dòng)效果代碼2008-06-06
Nuxt.js實(shí)現(xiàn)校驗(yàn)訪問瀏覽器類型的中間件
Nuxt.js 就是一個(gè)Vue的服務(wù)端渲染框架,和React的服務(wù)端渲染框架類似。這篇文章主要介紹了Nuxt.js實(shí)現(xiàn)校驗(yàn)訪問瀏覽器類型的中間件,需要的朋友可以參考下2018-08-08
JavaScript原型和原型鏈與構(gòu)造函數(shù)和實(shí)例之間的關(guān)系詳解
這篇文章主要介紹了JavaScript原型和原型鏈與構(gòu)造函數(shù)和實(shí)例之間的關(guān)系,每個(gè)對(duì)象都連接到一個(gè)原型對(duì)象,并且它可以從中繼承屬性。所有通過(guò)對(duì)象字面量創(chuàng)建的對(duì)象都連接到object.prototype,它是JavaScript中的標(biāo)配對(duì)象2022-07-07
js實(shí)現(xiàn)圖片360度旋轉(zhuǎn)
本文主要介紹了js實(shí)現(xiàn)圖片360度旋轉(zhuǎn)的思路與方法。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01
js保留兩位小數(shù)最簡(jiǎn)單的實(shí)現(xiàn)方法
JS數(shù)據(jù)格式化是在進(jìn)行web前端開發(fā)時(shí)常碰到的事情,特別是在數(shù)據(jù)類型為Float的數(shù)據(jù)就需要特殊處理,如保留兩位小數(shù)、小數(shù)點(diǎn)后的數(shù)據(jù)是否需要四舍五入等等,下面這篇文章主要給大家介紹了關(guān)于js保留兩位小數(shù)最簡(jiǎn)單的實(shí)現(xiàn)方法,需要的朋友可以參考下2023-05-05

