views:

16248

answers:

12

I'm trying to create globally-unique identifiers in Javascript. I'm not sure what routines are available on all browsers, how "random" and seeded the built-in random number generator is, etc..

The GUID / UUID should be at least 32 characters and should stay in the ASCII range to avoid trouble when passing them around.

+38  A: 

There have been a couple attempts at this. The question is: do you want actual GUIDs, or just random numbers that look like GUIDs? It's easy enough to generate random numbers. From http://note19.com/2007/05/27/javascript-guid-generator/:

function S4() {
   return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
function guid() {
   return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
}

However, note in the comments that such values are not genuine GUIDs. There's no way to generate real GUIDs in Javascript, because they depend on properties of the local computer that browsers do not expose. You'll need to use OS-specific services like ActiveX: http://p2p.wrox.com/topicindex/20339.htm

John Millikin
Actually, the RFC allows for UUIDs that are created from random numbers. You just have to twiddle a couple of bits to identify it as such.See section 4.4. Algorithms for Creating a UUID from Truly Random or Pseudo-Random Numbers:http://www.rfc-archive.org/getrfc.php?rfc=4122
Jason DeFontes
Essentially, this is the solution I use - the purpose for which I use it is simple enough that it's sufficient for my needs, though I could see it causing problems for people that have more technical demands. I suppose someone could hit the server for a GUID, depending on the specific need...
Jason Bunting
Could someone explain this code to me? It looks like the S4 function tries to get a random hex number between 0x10000 and 0x20000, then outputs the last 4 digits. But why the bitwise or with 0? Shouldn't that be a noop? Also, is the 0x10000 to 0x20000 just a hack to avoid having to deal with leading 0's?
Cory
+2  A: 

From sagi shkedy's technical blog:

function generateGuid() {
  var result, i, j;
  result = '';
  for(j=0; j<32; j++) {
    if( j == 8 || j == 12|| j == 16|| j == 20) 
      result = result + '-';
    i = Math.floor(Math.random()*16).toString(16).toUpperCase();
    result = result + i;
  }
  return result;
}

There are other methods that involve using an ActiveX control, but stay away from these!

EDIT: I thought it was worth pointing out that no GUID generator can guarantee unique keys (check the wikipedia article). There is always a chance of collisions. A GUID simply offers a large enough universe of keys to reduce the change of collisions to almost nil.

That being said, I think that the note19 solution posted by John Millikin is much more elegant that the one I found. Go with that.

Prestaul
Note that this isn't a GUID in the technical sense, because it does nothing to guarantee uniqueness. That may or may not matter depending on your application.
Stephen Deken
Ditto to Stephen's response. If you need uniqueness, define it server side where hopefully to can get to a proper algorithm!
Ray Hayes
Yep, this is Not a valid GUID!
pdavis
No GUID is guaranteed to be unique... The universe of created keys is simply large enough to make collisions nearly impossible.
Prestaul
A quick note about performance. This solution creates 36 strings total to get a single result. If performance is critical, consider creating an array and joining as recommended by:http://tinyurl.com/y37xtxFurther research indicates it may not matter, so YMMV:http://tinyurl.com/3l7945
Brandon DuRette
+9  A: 

A web service would be useful.

Quick Google found: http://www.hoskinson.net/GuidGenerator/

Can't vouch for this implementation, but SOMEONE must publish a bonafide GUID generator.

With such a web service, you could develop a REST web interface that consumes the GUID web service, and serves it through AJAX to javascript in a browser.

Sean
I made, host and use this one: http://www.timjeanes.com/guid. It uses .NET to generate a new GUID and returns it without any additional fluff. It'll also work over JSONP.
teedyay
+5  A: 

From good ol' wikipedia there's a link to a javascript implementation of UUID.

It looks fairly elegant, and could perhaps be improved by salting with a hash of the client's IP address. This hash could perhaps be inserted into the html document server-side for use by the client-side javascript.

Dan
+2  A: 

When looking about for a solution, don't just search on "GUID" but also try "UUID".

Guerry
+28  A: 

Here's some code based on RFC 4122, section 4.4 (Algorithms for Creating a UUID from Truly Random or Pseudo-Random Number).

function createUUID() {
    // http://www.ietf.org/rfc/rfc4122.txt
    var s = [];
    var hexDigits = "0123456789ABCDEF";
    for (var i = 0; i < 32; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[12] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
    s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01

    var uuid = s.join("");
    return uuid;
}
Kevin Hakanson
+2  A: 

This create version 4 UUID (created from pseudo random numbers) :

function uuid()
{
   var chars = '0123456789abcdef'.split('');

   var uuid = [], rnd = Math.random, r;
   uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
   uuid[14] = '4'; // version 4

   for (var i = 0; i < 36; i++)
   {
      if (!uuid[i])
      {
         r = 0 | rnd()*16;

         uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf];
      }
   }

   return uuid.join('');
}

Here is a sample of the UUIDs generated :

682db637-0f31-4847-9cdf-25ba9613a75c
97d19478-3ab2-4aa1-b8cc-a1c3540f54aa
2eed04c9-2692-456d-a0fd-51012f947136
Mathieu Pagé
+9  A: 

There's a nice compact function for creating rfc4122-compliant random UUIDs posted on my blog at:

http://www.broofa.com/2008/09/javascript-uuid-function/

Math.uuid.js is small (~400bytes), and has no dependencies on other libs, so can drop into just about any JS project. It can be used to produce either RFC4122-compliant v4 (random) uuids, or more compact, non-standard IDs of arbitrary length and base. For example:

>>> Math.uuid() // RFC4122 v4 UUID
"4FAC90E7-8CF1-4180-B47B-09C3A246CB67"

>>> Math.uuid(17) // 17 digits, base 62 (0-9,a-Z,A-Z)
"GaohlDbGYvOKd11p2"

>>> Math.uuid(5, 10) // 5 digits, base 10
"84274"

>>> Math.uuid(8, 16) // 8 digits, base 16
"19D954C3"

P.S. That blog post also links to a test page that shows the number of possible UUIDs there are for a variety of arguments, and that includes a performance test for those that care about that sort of thing.

broofa
+25  A: 

For an rfc4122 version 4 compliant solution, this one-liner(ish) solution is the most compact I could come up with.:

'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);
}).toUpperCase();

E.g:

>>> '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);}).toUpperCase();
"3BCE4931-6C75-41AB-AFE0-2EC108A30860"
broofa
I think I like this better than my answer.
Kevin Hakanson
+1 very nice solution
Tomas
+3  A: 

It's just a simple AJAX call...

If anyone is still interested, here's my solution.

On the server side:

[WebMethod()]
public static string GenerateGuid()
{
    return Guid.NewGuid().ToString();
}

On the client side:

var myNewGuid = null;
PageMethods.GenerateGuid(
    function(result, userContext, methodName)
    {
        myNewGuid = result;
    },
    function()
    {
        alert("WebService call failed.");
    }
);
alekop
Your method is the only correct way, but the problem with it is that it's asynchronous, so you can't really use that. Besides, try doing that a few 100 to 1000 times, and you will crash IE (not Chrome and Firefox, though). Synchronous calls would we needed: Use JQuery, not MS-PageMethod JavaScript !
Quandary
You're right, called asynchronously this is not very useful. Ironically my original code does use jQuery to invoke this method synchronously. Here's an example:$.ajax({ async: false, type: 'POST', url: 'MyPage.aspx/GenerateGuid', contentType: 'application/json; charset=utf-8', data: '{}', success: function(data) { // data contains your new GUID }, failure: function(msg) { alert(msg); }});
alekop
+3  A: 

David Bau provides a much better, seedable random number generator at http://davidbau.com/archives/2010/01/30/random_seeds_coded_hints_and_quintillions.html

I wrote up a slightly different approach to generating UUIDs at http://blogs.cozi.com/tech/2010/04/generating-uuids-in-javascript.html

George V. Reilly
+1  A: 
  // RFC 4122
  //
  // A UUID is 128 bits long
  //
  // String representation is five fields of 4, 2, 2, 2, and 6 bytes.
  // Fields represented as lowercase, zero-filled, hexadecimal strings, and
  // are separated by dash characters
  //
  // A version 4 UUID is generated by setting all but six bits to randomly
  // chosen values
  var uuid = [
    Math.random().toString(16).slice(2, 10),
    Math.random().toString(16).slice(2, 6),

    // 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
    (Math.random() * .0625 /* 0x.1 */ + .25 /* 0x.4 */).toString(16).slice(2, 6),

    // Set the two most significant bits (bits 6 and 7) of the
    // clock_seq_hi_and_reserved to zero and one, respectively
    (Math.random() * .25 /* 0x.4 */ + .5 /* 0x.8 */).toString(16).slice(2, 6),

    Math.random().toString(16).slice(2, 14)].join('-');
jablko