# snowflake-id-js **Repository Path**: kelr/snowflake-id-js ## Basic Information - **Project Name**: snowflake-id-js - **Description**: js版本的雪花算法,同时支持雪花ID的生成时间、数据中心ID、机器ID解析 - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2023-11-25 - **Last Updated**: 2025-09-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # snowflake-id-js ## 介绍 网上找了下好像没找到使用 js 生成雪花算法的相关工具。由于日常有时候测试数据使用的是雪花 ID,添加测试数据的时候要去打开 idea 跑 main 或者测试方法太耗时了。最近准备做一个工具集成页面,就想着把这个功能集成进来。 ## 生成方法 如果使用 java 的生成方式套到 js 里面就会存在精度问题(前后端对接的时候,后端使用 Long 类型直接把 ID 给前端,然后死活接口数据对不上,应该有同学遇到过吧)。java 版本(准确来说应该是所有版本,目前只使用 java 版本深入研究过雪花算法)雪花算法最后一步是使用位运算去生成 ID,在 js 这就存在精度问题了,拿不到真正的雪花 ID。 目前的做法是把时间戳、数据中心 ID、机器 ID、序列号每个数据分别转为二进制,并且把不足位数的部分使用 0 补足,组成一串二进制字符串,最后把这一串二进制字符串使用 BigInt 去解析,得到最后的雪花 ID。 ## 时钟回拨问题 直接使用最后一个 id 生成时间作为当前时间(其实这个问题在前端这刷新一下页面就好了) ## 一点点的其他小用处 例如 vue 的 v-for 中,后端刚好没把列表 id 给前端,前端可以使用这个算法去生成 id,用于 key 的绑定,避免使用 index 去绑定 key。 如果前端使用了 indexeddb,也可以用这个去生成 table 的 ID。 ## 使用 `Snowflake`构造函数四个参数分别是数数据中心 ID(默认 0),机器 ID(默认 0),开始序列号是否随机(默认 false,true 的时候初始化序列号会在 0-100 之间随机取一个数,后端可以用这个方法避免数据倾斜),起始时间(默认 1288834974657),支持一次获取多个 ID,在`nextId`方法存在两个参数,第一个为获取数量(默认 1),第二个参数为`singleReturnStr` `Boolean`类型,表示获取一个 ID 是否以字符串类型返回,默认为 true,设置为 false 的时候会以数组形式返回 ### 默认方法 ```javascript const snowflake = new Snowflake(); // 返回单个id 用数组形式返回 // const id1 = snowflake.nextId(1, false) // console.log('id1:', id1) // 返回单个id 默认用字符串形式返回 const id = snowflake.nextId(); console.log("nextId:", id); console.log("timestamp:", snowflake.parseIdGenerateTime(id)); console.log("time:", new Date(snowflake.parseIdGenerateTime(id))); console.log("datacenter:", snowflake.parseDataCenterId(id)); console.log("workId:", snowflake.parseWorkerId(id)); ``` ### 定制化方式 ```javascript const snowflake = new Snowflake(31, 31, true, 1288834974657); const ids = snowflake.nextId(10); console.log("nextId:", ids); console.log("timestamp:", snowflake.parseIdGenerateTime(ids[0])); console.log("time:", new Date(snowflake.parseIdGenerateTime(ids[0]))); console.log("datacenter:", snowflake.parseDataCenterId(ids[0])); console.log("workId:", snowflake.parseWorkerId(ids[0])); ``` 具体可以参考 demo/demo.html 里面的代码 ### vue 中使用 > vue 中使用需要把 snowflake.js 最后面的注释打开`export default Snowflake` #### vue3 使用 ```javascript import { onMounted } from "vue"; import Snowflake from "@/util/snowflake"; const snowflake = new Snowflake(31, 31, true); onMounted(() => { const ids = snowflake.nextId(10); console.log("nextId:", ids); console.log("timestamp:", snowflake.parseIdGenerateTime(ids[0])); console.log("time:", new Date(snowflake.parseIdGenerateTime(ids[0]))); console.log("datacenter:", snowflake.parseDataCenterId(ids[0])); console.log("workId:", snowflake.parseWorkerId(ids[0])); }); ``` #### vue2 使用 ```javascript import Snowflake from "@/util/snowflake"; export default { name: "Snowflake", data() { return { snowflake: new Snowflake(0, 0, true), }; }, mounted() { const ids = this.snowflake.nextId(10); console.log("nextId:", ids); console.log("timestamp:", this.snowflake.parseIdGenerateTime(ids[0])); console.log("time:", new Date(this.snowflake.parseIdGenerateTime(ids[0]))); console.log("datacenter:", this.snowflake.parseDataCenterId(ids[0])); console.log("workId:", this.snowflake.parseWorkerId(ids[0])); }, }; ``` ## 支持解析 ID 的生成时间、数据中心 ID、机器 ID 参数 - 解析 ID 生成时间:`snowflake.parseIdGenerateTime(snowflakeId)` 返回生成的时间戳,需要转时间自行转换 - 解析数据中心 ID:`snowflake.parseDataCenterId(snowflakeId)` - 解析机器 ID:`snowflake.parseWorkerId(snowflakeId)` ## 测试结果 经过 5 轮测试,第四第五轮关闭电脑部分软件略微提升,1 秒钟内大致可以产生 60-70 万个 ID **第一次测试** ![](./images/test1.jpg) **第二次测试** ![](./images/test2.jpg) **第三次测试** ![](./images/test3.jpg) **第四次测试** ![](./images/test4.jpg) **第五次测试** ![](./images/test5.jpg) ### 结果检测 检测生成的 60 万个 ID 是否存在重复:由于 60 万个 ID 转 json 会卡死,切成 10 万个一个文件,最后将这 6 个文件进行检查,无重复 ID ![](./images/id_download.png) ![](./images/id_check.png)