如何使用node.js生成唯一ID


174
function generate(count) {
    var founded = false,
        _sym = 'abcdefghijklmnopqrstuvwxyz1234567890',
        str = '';
    while(!founded) {
        for(var i = 0; i < count; i++) {
            str += _sym[parseInt(Math.random() * (_sym.length))];
        }
        base.getID(string, function(err, res) {
            if(!res.length) {
                founded = true; // How to do it?
            }
        });
    }
    return str;
}

如何使用数据库查询回调设置变量值?我该怎么办?


@JamesAllardice,我需要了解如何通过数据库查询来完成。对不起,谢谢
猫头鹰

1
该问题被错误地标记为重复。链接的问题回答了如何在通用javascript中做到这一点;这个问题中评分最高的答案特定于node.js。
Mike Post

5
我想将其粘贴为答案:var hexstring = crypto.randomBytes(16).toString("hex");之后var guidstring = hexstring.substring(0,8) + "-" + hexstring.substring(8,12) + "-" + hexstring.substring(12,16) + "-" + hexstring.substring(16,20) + "-" + hexstring.substring(20);
selbie

这是一个很好的答案,new mongo.ObjectID();并手动stackoverflow.com/a/56106999/4701635
Paresh Barad

Answers:


18

自从我使用node.js已经有一段时间了,但是我想我可以提供帮助。

首先,在node中,您只有一个线程,应该使用回调。您的代码将发生的情况是base.getID查询将排队等待执行,但是while循环将毫无意义地连续作为繁忙循环运行。

您应该可以通过以下回调来解决您的问题:

function generate(count, k) {
    var _sym = 'abcdefghijklmnopqrstuvwxyz1234567890',
    var str = '';

    for(var i = 0; i < count; i++) {
        str += _sym[parseInt(Math.random() * (_sym.length))];
    }
    base.getID(str, function(err, res) {
        if(!res.length) {
          k(str)                   // use the continuation
        } else generate(count, k)  // otherwise, recurse on generate
    });
}

并这样使用它

generate(10, function(uniqueId){
  // have a uniqueId
})

大约两年来我没有编写任何node / js的代码,也没有进行测试,但是基本思想应该成立-不要使用繁忙的循环,而应使用回调。您可能想看看节点异步包。


4
当需要真正随机的ID时,尤其是在需要不可预测的/密码安全的情况下,Math.random是一个糟糕的选择。
Jecho Jekov

324

安装NPM uuid软件包(来源:https : //github.com/kelektiv/node-uuid):

npm install uuid

并在您的代码中使用它:

var uuid = require('uuid');

然后创建一些ID ...

// Generate a v1 (time-based) id
uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'

// Generate a v4 (random) id
uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'

** UPDATE 3.1.0 不建议使用
以上用法,因此请像下面这样使用此程序包:

const uuidv1 = require('uuid/v1');
uuidv1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' 

const uuidv4 = require('uuid/v4');
uuidv4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1' 

** UPDATE 7.x
并且现在不建议使用上述用法,因此请使用以下程序包:

const { v1: uuidv1 } = require('uuid');
uuidv1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' 

const { v4: uuidv4 } = require('uuid');
uuidv4(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' 

谢谢,但是我需要通过数据库查询来完成。:)
猫头鹰

@owl我不明白你的意思。在SQL中?
Vinz243 2014年

51
如果在数据库查询中,它有什么区别?您有一个唯一的ID,现在可以在与数据库通信的任何接口中使用它。
jraede 2014年

知道uuid和node-uuid软件包之间有什么区别吗?
ishandutta2007 '01

5
不推荐使用@ ishandutta2007 node-uuid:“已弃用:请改用uuid软件包。”
diutsu

236

在Node中创建随机的32个字符的字符串的最快方法是使用本机crypto模块:

const crypto = require("crypto");

const id = crypto.randomBytes(16).toString("hex");

console.log(id); // => f9b327e70bbcf42494ccb28b2d98e00e

53
我喜欢这种解决方案,因为不需要外部依赖。我也发现base64版本也很有用。crypto.randomBytes(3*4).toString('base64') //=> '9uzHqCOWI9Kq2Jdw'
hiroshi

5
它是随机的还是唯一的?请详细说明随机函数。
Maximi

“生成加密强度高的伪随机数据。” API
Stanislasdrg恢复莫妮卡

1
crypto:现在内置节点本身。你如果NPM安装它得到这样的警告crypto@1.0.1: This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in
永恒之塔

1
现在,这将导致弃用警告。
拉兹

34

另一种方法是使用npm 的shortid软件包。

这是非常容易使用:

var shortid = require('shortid');
console.log(shortid.generate()); // e.g. S1cudXAF

并具有一些引人注目的功能:

ShortId创建令人惊讶的短非连续url友好的唯一ID。非常适合网址缩短器,MongoDB和Redis ID,以及其他用户可能会看到的ID。

  • 默认情况下,7-14个网址友好字符:AZ,az,0-9,_-
  • 非顺序的,因此它们是不可预测的。
  • 可以生成任意数量的ID(无重复),甚至每天数百万。
  • 应用程序可以重新启动任何次数,而无需重复输入ID。

“应用程序可以重新启动任何次数,而无需重复ID。” 你能告诉我shortid是如何工作的吗?
海军圣火

@NavyFlame在这里你去:github.com/dylang/shortid或者更具体github.com/dylang/shortid/issues/95
海峡

21

node-uuid 已弃用,请使用 uuid

npm install uuid --save
// Generate a v1 UUID (time-based) 
const uuidV1 = require('uuid/v1');
uuidV1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' 

// Generate a v4 UUID (random) 
const uuidV4 = require('uuid/v4');
uuidV4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1' 

Npm连结


19

简单,基于时间,没有依赖关系:

(new Date()).getTime().toString(36)

输出: jzlatihl


加上随机数(感谢@Yaroslav Gaponov的回答)

(new Date()).getTime().toString(36) + Math.random().toString(36).slice(2)

输出量 jzlavejjperpituute


9

更简单,无需添加模块

Math.random().toString(26).slice(2)

2
我认为这取决于长度。因此您可以像内联一样扩展此代码function getId(mask) { return mask.replace(/[x]/gi, () => { return Math.random().toString(26)[5]; }) } console.log(getId('xxxx-xxxx-xxxx-xxxx-xxxx-xxxx'));
Yaroslav Gaponov

6
当需要真正随机的ID时,尤其是在需要不可预测的/密码安全的情况下,Math.random是一个糟糕的选择。
Jecho Jekov

1
这不会生成真正通用的唯一ID。
vicg

@JechoJekov“真正随机”吗?我对此表示怀疑
-JDrake

是的,YaroslavGaponov可能是正确的,因为在真实空间[0,1]中分数相同的机会是0。编写了代码以生成1,000,000 Math.random()并且找不到任何重复项。random_numbers = [] for (i = 0; i < 1000000; i++) { random_numbers.push(Math.random()) } if (i === 1000000) { console.log("Before checking duplicate") console.log(random_numbers.length) console.log("After checking duplicate") random_set = new Set(random_numbers) console.log([...random_set].length) }
Yi Xiang Chong

3

如果有人需要加密强度很高的UUID,那么也有解决方案。

https://www.npmjs.com/package/generate-safe-id

npm install generate-safe-id

为什么不使用UUID?

随机UUID(UUIDv4)的熵不足以使其具有唯一性(ironic ,eh?)。随机UUID仅具有122位熵,这表明只有2 ^ 61个 ID 后才会出现重复。另外,某些UUIDv4实现不使用加密强度高的随机数生成器。

该库使用Node.js加密RNG 生成240位 ID,这表明第一个重复项将在生成2 ^ 120个 ID 之后发生。根据当前人类的能源生产,在可预见的未来,这个门槛将无法跨越。

var generateSafeId = require('generate-safe-id');

var id = generateSafeId();
// id == "zVPkWyvgRW-7pSk0iRzEhdnPcnWfMRi-ZcaPxrHA"

9
由于generate-safe-id被遗弃且安全漏洞未修复,此答案可能不再对用户有效(截至2018年8月)
dannypaz

1

我正在使用以下内容,并且在没有任何第三方依赖的情况下工作正常。

const {
  randomBytes
} = require('crypto');

const uid = Math.random().toString(36).slice(2) + randomBytes(8).toString('hex') + new Date().getTime();


1

在npm中使用https://www.npmjs.com/package/uniqid

npm i uniqid

它将始终根据当前时间,进程和计算机名称创建唯一的ID。

  • 在当前时间,ID在单个过程中始终是唯一的。
  • 使用进程ID,即使同时从多个进程中调用,该ID也是唯一的。
  • 使用MAC地址,即使同时从多个机器和进程中调用,ID也是唯一的。

特征:-

  • 非常快
  • 即使同时调用,也会在多个进程和机器上生成唯一的ID。
  • 较短的8和12字节版本,唯一性较少。

1

安装uuid

npm install --save uuid

uuid已更新且旧导入

const uuid= require('uuid/v4');

无法正常工作,我们现在应该使用此导入

const {v4:uuid} = require('uuid');

并使用它作为像这样的功能=>

const  createdPlace = {
    id: uuid(),
    title,
    description,
    location:coordinates,
    address,
    creator
  };

0

YaroslavGaponov的答案扩展,最简单的实现就是使用Math.random()

Math.random()

理论上,在实空间[0,1]中分数的几率相同,对于node.js中默认的16位小数长度,其几率是0,并且接近于0。由于不执行任何操作,因此该实现还应减少算术溢出。而且,与字符串相比,它的内存效率更高,因为小数比字符串占用更少的内存。

我将此称为“崇分数部分唯一ID”。我还没有写过一篇有关它的特性的论文,希望我能尽快得到它。

编写代码以生成1,000,000个Math.random()数字,并且找不到任何重复项(至少对于默认的小数点为16)。请参见下面的代码(如果有请提供反馈):

random_numbers = [] 
for (i = 0; i < 1000000; i++) { 
   random_numbers.push(Math.random()) 
   //random_numbers.push(Math.random().toFixed(13)) //depends decimals default 16 
} 

if (i === 1000000) { 
   console.log("Before checking duplicate") 
   console.log(random_numbers.length) 
   console.log("After checking duplicate") 
   random_set = new Set(random_numbers) 
   console.log([...random_set].length) // length is still the same
} 

此外,它取决于小数位数。我发现13个以上的小数random_numbers.push(Math.random().toFixed(13))仍具有相同的长度
Yi Xiang Chong
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.