• 只有踩过坑才懂:前端生成唯一 ID,别用 Date.now ()了!试试它crypto.randomUUID()


    前言

    有些时候,我们需要生成唯一 ID
    看上去很简单的样子,但真要做到百分百不重复,可比想的要坑。

    第一个坑:拿时间戳加随机数凑数

    很多小伙伴的第一反应可能会这样来写

    function backUniqueIDvalue() {
      return Date.now().toString(36) + Math.random().toString(36).substr(2);
    }
    

    简单解释一下这段代码的意思
    Date.now().toString(36)

    Date.now():获取当前的时间戳(精确到毫秒的数字)。
    toString(36):将这个时间戳数字转换为 36 进制的字符串。
    36 进制包含 0-9 和 a-z(10数字+26个字母)。
    这样可以让原本很长的数字时间戳变得非常短,且包含字母

    简单解释一下这段代码的意思
    Math.random().toString(36).substr(2)
    Math.random():生成一个 0 到 1 之间的随机小数(例如 0.123456789)。
    .toString(36):同样把这个小数转换为 36 进制字符串(例如 "0.4fzyo82mvyr")。
    .substr(2):截取从第 2 位开始的字符串,目的是去掉开头的 "0.",只保留后面的随机字符部分。

    举个例子:
    如果当前时间戳转 36 进制是 "lxixn9",
    随机数转 36 进制是 "0.abc123"
    那么最终拼接的结果就是类似 "lxixn9abc123" 这样的一串短 ID

    可能会出现的问题

    看着好像是没有问题的,而且代码也挺简单的。
    但是实际上放到生产环境中,这就是个定时炸弹

    时间戳精度不够

    Date.now()只能精确到毫秒,要是在同一毫秒里连续调用两次这个函数。
    那么就会返回相同的结果,此时 ID 的前半段就会完全一样
    我们都知道 Math.random()这玩意生成的不是真正的随机数,只是伪随机数。
    运气不好的时候,在较短时间内可能跑出一模一样的序列
    说到这里,小伙伴们可能已经知道,生成的 ID 唯一性可能不是那么高,可能会重复的。

    第二个坑:用自增的计数器

    还其他小伙伴想的更简单:整个全局的数字。
    每次生成 ID 就把数字加 1,从 0 开始往上排不就得了?
    但是如果用户开了俩同款页面,每个页面的计数器都是从零开始算,生成的 ID 会直接重复。
    显然,这样的办法不太行。
    这个时候,今天我们的主角就要闪亮登场了。
    掌声有请:crypto.randomUUID()
    下面我们简单介绍一下我们的专家大拿

    crypto.randomUUID() 是 ES2023标准 API

    crypto.randomUUID() 是 ES2023标准 API.
    ES2023(即 ECMAScript 2023)是在 2023年 正式推出的。

    crypto.randomUUID() 浏览器的版本要求

    浏览器环境:Chrome 92+、Firefox 95+、Safari 15.4+。
    该 API 只能在安全上下文(即 HTTPS 或 localhost)中使用(重要)。

    判断浏览器是否支持 crypto.randomUUID()

    判断是否支持crypto.randomUUID()。
    使用 typeof 检查typeof是否是 undefined
    然后使用 typeof 检查crypto.randomUUID是否是一个函数
    如果都成立的话,说明支持

    // 兼容性写法
    let uniqueId;
    if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
      // 现代环境直接使用原生 API
      uniqueId = crypto.randomUUID();
      // 生成的是:96e74085-38de-46bf-ba25-f85fe1bafc9d 这种格式的字符串
    } else {
      // 旧环境降级方案(例如引入 uuid 第三方库)
      // uniqueId = uuid.v4(); 
      console.warn('当前环境不支持 crypto.randomUUID');
    }
    

    为啥说这个是王者呢?

    即使你以每秒生成 10 亿 个 UUID 的速度,持续生成 100 年。
    发生一次重复的概率依然低于 10⁻³⁶(即 1 后面跟着 36 个零)。
    换句话说,你需要生成大约 2.71 万亿个id,才会有十亿分之一的概率发生一次重复。
    小伙伴们是不是觉得很厉害呢?

    crypto.randomUUID()需要注意的点

    大家应该看到了这样一句话:
    该 API 只能在安全上下文(即 HTTPS 或 localhost)中使用。
    换一句话说:
    本地开发时:使用 localhost 或 127.0.0.1 访问,它是可以正常工作的。
    如果你的网页是通过普通的 http:// 协议
    (例如 http://192.168.1.10http://xxx.com)访问的
    浏览器就会出于安全考虑,直接禁用这个 API。此时调用它。
    控制台通常会报错 TypeError: crypto.randomUUID is not a function。

    crypto.randomUUID()也是不想象中的那样强大

    本来以为是瑶瑶领先同行的。结果还隐藏着安全上下文的限制

    其他生成唯一 id 第三方库 uuid 库

    安装:npm install uuid
    使用:

    import { v4 as uuidv4 } from 'uuid'; 
    const id = uuidv4();
    

    其他的办法生成唯一 id

    我旁边机智的小伙伴说:这样写也可以

    Math.random() + Math.random()+ Math.random()+ Math.random()
    

    实在绷不住了,哈哈

  • 相关阅读:
    【软件测试】如何用python连接Linux服务器
    asp.net C#免费反编译工具ILSpy
    SPI和API还在傻傻分不清楚?
    java boolean占用内存是多少
    【四】3D Object Model之创建Creation——set_object_model_3d_attrib_mod()/union_object_model_3d()算子
    Java实现自动发聊天消息
    从new File("")到jdk源码
    24、Flink 的table api与sql之Catalogs(java api操作数据库、表)-2
    09_Webpack打包工具
    v-bind指令的详细介绍
  • 原文地址:https://www.cnblogs.com/IwishIcould/p/20213961