Snowflake(雪花算法)的JavaScript(JS)实现

位置:首页>文章>详情   分类: 教程分享 > WEB基础   阅读(1042)   2023-03-28 11:29:14

类库方式实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/big-integer/1.6.32/BigInteger.min.js"></script>
    <!-- <script src="http://peterolson.github.com/BigInteger.js/BigInteger.min.js"></script> -->
    <script>
        var 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;
                //设置默认值,从环境变量取
                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;
        }());
        var tempSnowflake = new Snowflake(1, 1, 0);
        var tempIds = [];
        console.time();
        for (var i = 0; i < 10000; i++) {
            var tempId = tempSnowflake.nextId();
            console.log(tempId);
            if (tempIds.indexOf(tempId) < 0) {
                tempIds.push(tempId);
            }
        }
        console.log(tempIds.length);
        console.timeEnd();
    </script>
</body>

</html>

原生BigInt实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        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;
                //设置默认值,从环境变量取
                this.workerId = 1n;
                this.dataCenterId = 1n;
                this.sequence = 0n;
                if (this.workerId > this.maxWrokerId || this.workerId < 0) {
                    throw new Error('_workerId must max than 0 and small than maxWrokerId-[' + this.maxWrokerId + ']');
                }
                if (this.dataCenterId > this.maxDataCenterId || this.dataCenterId < 0) {
                    throw new 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) {
                    throw new 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.time();
        var tempSnowflake = new Snowflake(1n, 1n, 0n);
        var tempIds = [];
        for (var i = 0; i < 10000; i++) {
            var tempId = tempSnowflake.nextId();
            console.log(tempId);
            if (tempIds.indexOf(tempId) < 0) {
                tempIds.push(tempId);
            }
        }
        console.log(tempIds.length);
        console.timeEnd();
    </script>
</body>

</html>


 
标签:
地址:https://www.leftso.com/article/944.html

相关阅读

类库方式实现:&lt;!DOCTYPE html&gtl; &lt;html lang="en"&gtl; &lt;head&gtl; &lt;meta charset="UTF-8"...
javascript(js)onclick 传递多个字符变量参数&lt;a title="点击下载附件" onclick="downloadFile(\''+row.url+'\',\''+ro...
JavaScript集合(Array)转树(tree)结构js 原生数组转树形结构 /** * 将list装换成tree * @param {Object} myId 数据主键id * ...
现有js数组数据如下:let dataArray=[{id:1,name:'张三'},{id:2,name:'李四'}];根据id获取js数组的对象let findId=1; let findO...
这里讲解的是一种通过扩展原生JS的方式进行日期格式化​首先,在需要使用的地方添加以下代码Date.prototype.format = function(fmt) { var o ...
js 生成二维码引入qrcode.js该框架基于HTML5原生编写,兼容性较好。支持H5 vue uniapp 微信小程序等。基本使用参考&lt;div id="qrcode"&gtl;&lt;...
​JavaScript 数学小数精确计算&lt;!DOCTYPE html&gtl; &lt;html&gtl; &lt;head&gtl; &lt;title&gtl;&lt;/tit...
清空input 类型为file的文件选择常见的方法分两类一. javascript 方式清空file选择首先获取dom元素filevar file=document.getElementById...
&lt;body&gtl; &lt;script type="text/javascript"&gtl;   function test(){     let obj={        ...
Ajax Post 下载文件通过原生js实现function ajaxPostDownload(url,fileName,callback) { let xhr = new XMLHtt...