20

I need to generate unique ids in the browser. Currently, I'm using this:

Math.floor(Math.random() * 10000000000000001)

I'd like to use the current UNIX time ((new Date).getTime()), but I'm worried that if two clients generate ids at the exact same time, they wouldn't be unique.

Can I use the current UNIX time (I'd like to because that way ids would store more information)? If not, what's the best way to do this (maybe UNIX time + 2 random digits?)

Tom Lehman
  • 85,973
  • 71
  • 200
  • 272
  • Possible duplicate of [Create GUID / UUID in JavaScript?](https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript) – krock Aug 10 '18 at 00:54

7 Answers7

17

you can create a GUID using the following links:

http://softwareas.com/guid0-a-javascript-guid-generator

Create GUID / UUID in JavaScript?

This will maximise your chance of "uniqueness."

Alternatively, if it is a secure page, you can concatenate the date/time with the username to prevent multiple simultaneous generated values.

Community
  • 1
  • 1
Russell
  • 17,481
  • 23
  • 81
  • 125
11

https://github.com/uuidjs/uuid provides RFC compliant UUIDs based on either timestamp or random #'s. Single-file with no dependencies, supports timestamp or random #-based UUIDs, uses native APIs for crypto-quality random numbers if available, plus other goodies.

broofa
  • 37,461
  • 11
  • 73
  • 73
7

In modern browser you can use crypto:

var array = new Uint32Array(1);
window.crypto.getRandomValues(array);
console.log(array);
Jules Goullee
  • 571
  • 4
  • 11
1
var c = 1;
function cuniq() {
    var d = new Date(),
        m = d.getMilliseconds() + "",
        u = ++d + m + (++c === 10000 ? (c = 1) : c);

    return u;
}
  • why is `c` outside of the variables declaration in `cuniq()` ? Also, could you please explain the logic behind this algorithm? – vsync Oct 20 '16 at 13:35
  • @vsync it allots an incrementing sub component 'c'. This is a local affectation to increase the likeliness of global uniqueness spreading those values modulo 10000 over a millisecond / date based prefix. YMMV – twobob Jun 13 '17 at 01:25
1

Here is my javascript code to generate guid. It does quick hex mapping and very efficient:

AuthenticationContext.prototype._guid = function () {
    // RFC4122: The version 4 UUID is meant for generating UUIDs from truly-random or
    // pseudo-random numbers.
    // The algorithm is as follows:
    //     Set the two most significant bits (bits 6 and 7) of the
    //        clock_seq_hi_and_reserved to zero and one, respectively.
    //     Set the four most significant bits (bits 12 through 15) of the
    //        time_hi_and_version field to the 4-bit version number from
    //        Section 4.1.3. Version4 
    //     Set all the other bits to randomly (or pseudo-randomly) chosen
    //     values.
    // UUID                   = time-low "-" time-mid "-"time-high-and-version "-"clock-seq-reserved and low(2hexOctet)"-" node
    // time-low               = 4hexOctet
    // time-mid               = 2hexOctet
    // time-high-and-version  = 2hexOctet
    // clock-seq-and-reserved = hexOctet: 
    // clock-seq-low          = hexOctet
    // node                   = 6hexOctet
    // Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
    // y could be 1000, 1001, 1010, 1011 since most significant two bits needs to be 10
    // y values are 8, 9, A, B
    var guidHolder = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
    var hex = '0123456789abcdef';
    var r = 0;
    var guidResponse = "";
    for (var i = 0; i < 36; i++) {
        if (guidHolder[i] !== '-' && guidHolder[i] !== '4') {
            // each x and y needs to be random
            r = Math.random() * 16 | 0;
        }

        if (guidHolder[i] === 'x') {
            guidResponse += hex[r];
        } else if (guidHolder[i] === 'y') {
            // clock-seq-and-reserved first hex is filtered and remaining hex values are random
            r &= 0x3; // bit and with 0011 to set pos 2 to zero ?0??
            r |= 0x8; // set pos 3 to 1 as 1???
            guidResponse += hex[r];
        } else {
            guidResponse += guidHolder[i];
        }
    }

    return guidResponse;
};
Omer Cansizoglu
  • 1,271
  • 9
  • 14
0

You can always run a test against existing IDs in the set to accept or reject the generated random number recursively.

for example:

const randomID = function(){
    let id = Math.floor(Math.random() * 10000000000000001) + new Date();

    if (idObjectArray.contains(id)) {
    randomID;
} else {
    idObjectArray.push(id);
}
};

This example assumes you would just be pushing the id into a 1D array, but you get the idea. There shouldn't be many collisions given the uniqueness of the random number with the date, so it should be efficient.

Len Joseph
  • 1,406
  • 10
  • 21
0

There are two ways to achieve this

  1. js const id = Date.now().toString()

While this does not guarantee uniqueness (When you are creating multiple objects within 1ms), this will work on a practical level, since it is usually not long before the objects on the client are sent to a real server.

  1. If you wanted to create multiple records withing 1ms, I suggest using the code below
const { randomBytes } = require("crypto");

// 32 Characters
const id = randomBytes(16).toString("hex");

It works similar to a uuid4 without needing to add an external library (Assuming you have access to NodeJs at some point)

Malik Bagwala
  • 2,695
  • 7
  • 23
  • 38
  • 1
    Great answer! Using UUID might seem more sophisticated - but you can easily reduce the bundle size by using the suggested answer. The question that should be asked: How likely is it that two objects will be created in the exact same ms. – pa1nd Sep 13 '20 at 00:40
  • @pa1nd I cleaned up the answer and added another way which may be a way to go – Malik Bagwala Sep 16 '20 at 04:54