Starting from Chome92 version, crypto module already supports randomUUID() method.

1. The old way

In front-end web, we usually use timestamp or Math.random() when generating a uuid. For example, on stackoverflow, there is a famous code: How to create a GUID / UUID, which is generated by Math.random().

1
2
3
4
5
6
7
8
9
function uuidv4() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
    var r = (Math.random() * 16) | 0,
      v = c == 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}

console.log(uuidv4()); // "f94adc58-89b7-4c70-bc92-2935ea6fb5d2" 格式一样,但每次都不一样

The random() method is called once for each position.

2. randomUUID

Chrome now has native support for the uuId method, crypto.randomUUID(), starting with version 92.

1
crypto.randomUUID();

sobyte

This randomUUID() method can be used in the future when you want to get a random value, or to identify a device (under less demanding conditions).

3. Summary

randomUUID(), a browser-provided native, does work well and conforms to the v4 version of the format.

But there is one drawback: compatibility is too poor. Not only is it not supported by other browsers, but even in Chrome, it is only available from version 92 onwards.

But I believe other browsers will support this method in the near future.

Let’s write a front-end method to get uuid.

  1. use crypto.randomUUID as a preference.
  2. if not, use preferentially use crypto.getRandomValues.
  3. use Math.random() for underwriting.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const generateUUID = () => {
  if (typeof crypto === 'object') {
    if (typeof crypto.randomUUID === 'function') {
      // https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID
      return crypto.randomUUID();
    }
    if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
      // https://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid
      const callback = (c) => {
        const num = Number(c);
        return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(16);
      };
      return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, callback);
    }
  }
  let timestamp = new Date().getTime();
  let perforNow = (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0;
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    let random = Math.random() * 16;
    if (timestamp > 0) {
      random = (timestamp + random) % 16 | 0;
      timestamp = Math.floor(timestamp / 16);
    } else {
      random = (perforNow + random) % 16 | 0;
      perforNow = Math.floor(perforNow / 16);
    }
    return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16);
  });
};