繁体   English   中英

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

[英]How to generate unique ID with node.js

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;
}

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

安装 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'

**更新 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' 

**更新 7.x
现在上面的用法也被弃用了,所以像这样使用这个包:

const { 
  v1: uuidv1,
  v4: uuidv4,
} = require('uuid');

uuidv1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a' 
uuidv4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1' 

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

const crypto = require("crypto");

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

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

从 Node 14.17.0 开始,您现在可以使用内置的加密模块来生成 UUID(UUIDv4 Flavored):

const { randomUUID } = require('crypto'); // Added in: node v14.17.0

console.log(randomUUID());

// '89rct5ac2-8493-49b0-95d8-de843d90e6ca'

有关更多信息,您可以探索https://nodejs.org/api/crypto.html#crypto_crypto_randomuuid_options

注意: crypto.randomUUID比 uuid 快三倍。 并且不需要添加额外的依赖。

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

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

或者

Date.now().toString(36)

输出: jzlatihl


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

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

输出jzlavejjperpituute

编辑:shortid 已被弃用。 维护人员建议改用nanoid


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

这是非常容易使用:

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

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

ShortId 创建了非常短的非顺序 url 友好的唯一 id。 非常适合 url 缩短器、MongoDB 和 Redis id 以及任何其他用户可能看到的 id。

  • 默认情况下 7-14 个 url 友好字符:AZ、az、0-9、_-
  • 非顺序的,因此它们是不可预测的。
  • 可以生成任意数量的没有重复的 id,甚至每天数百万。
  • 应用程序可以重新启动任意次数,而没有任何重复 id 的机会。

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

首先,在节点中,你只有一个线程并且应该使用回调。 您的代码会发生什么, 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
})

我在大约 2 年的时间里没有编写任何 node/js 代码,也没有对此进行测试,但基本思想应该成立—​​—不要使用繁忙的循环,并使用回调。 您可能想看看节点异步包。

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 链接

更简单,无需添加模块

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

安装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
  };

如果您使用节点 v15.6.0+,我们可以使用crypto.randomUUID([options]) 完整的文档在这里

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

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

npm install generate-safe-id

为什么不使用 UUID?

随机 UUID (UUIDv4)没有足够的熵来普遍唯一(讽刺的是,嗯?)。 随机 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"

我的 5 美分:

const crypto = require('crypto');

const generateUuid = () => {
  return [4, 2, 2, 2, 6] // or 8-4-4-4-12 in hex
    .map(group => crypto.randomBytes(group).toString('hex'))
    .join('-');
};

Pono的字符串遗憾地缺少连字符,所以它不符合uuid 标准,我相信这是大多数人来这里的目的。

> generateUuid();
'143c8862-c212-ccf1-e74e-7c9afa78d871'
> generateUuid();
'4d02d4d6-4c0d-ea6b-849a-208b60bfb62e'

我想用这个

 class GUID { Generate() { const hex = "0123456789ABCDEF"; const model = "xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx"; var str = ""; for (var i = 0; i < model.length; i++) { var rnd = Math.floor(Math.random() * hex.length); str += model[i] == "x" ? hex[rnd] : model[i] ; } return str.toLowerCase(); } } console.log(new GUID().Generate()); console.log(new GUID().Generate()); console.log(new GUID().Generate()); console.log(new GUID().Generate()); console.log(new GUID().Generate());

我正在使用以下内容,它工作正常,而且没有任何第三方依赖项。

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

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

nanoid实现了您想要的完全相同的东西。

示例用法:

const { nanoid } = require("nanoid")

console.log(nanoid())
//=> "n340M4XJjATNzrEl5Qvsh"

这里的解决方案很旧,现在已弃用: https ://github.com/uuidjs/uuid#deep-requires-now-deprecated

用这个:

npm 安装 uuid

//add these lines to your code
const { v4: uuidv4 } = require('uuid');
var your_uuid = uuidv4();
console.log(your_uuid);

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

npm i uniqid

它将始终根据当前时间、进程和机器名称创建唯一 ID。

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

特征:-

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

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

Math.random()

从数学上讲,在实际空间 [0, 1] 中分数相同的概率理论上是 0。在概率方面,对于 node.js 中的 16 位小数的默认长度,它大约接近 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); // Set removes duplicates
   console.log([...random_set].length); // length is still the same after removing
} 

您可以使用 urid 包npm install urid

import urid from 'urid';

urid(); // qRpky22nKJ4vkbFZ

在此处阅读完整文档: https ://www.npmjs.com/package/urid

// Set the size
urid(8); //ZDJLC0Zq

// Use the character set
urid('num'); // 4629118294212196
urid('alpha'); // ebukmhyiagonmmbm
urid('alphanum'); // nh9glmi1ra83979b

// Use size with character set
urid(12, 'alpha'); // wwfkvpkevhbg

// use custom character set
urid(6, '0123456789ABCDEF'); // EC58F3
urid('0123456789ABCDEF'); // 6C11044E128FB44B

// some more samples
urid()               // t8BUFCUipSEU4Ink
urid(24)             // lHlr1pIzAUAOyn1soU8atLzJ
urid(8, 'num')       // 12509986
urid(8, 'alpha')     // ysapjylo
urid(8, 'alphanum')  // jxecf9ad

// example of all character sets
urid('num')          // 5722278852141945
urid('alpha')        // fzhjrnrkyxralgpl
urid('alphanum')     // l5o4kfnrhr2cj39w
urid('Alpha')        // iLFVgxzzUFqxzZmr
urid('ALPHA')        // ALGFUIJMZJILJCCI
urid('ALPHANUM')     // 8KZYKY6RJWZ89OWH
urid('hex')          // 330f726055e92c51
urid('HEX')          // B3679A52C69723B1

// custom character set
urid('ABCD-')        // ACA-B-DBADCD-DCA

生成加密的强伪随机数据。 size 参数是一个数字,指示要生成的字节数。

// Asynchronous
const {
  randomBytes,
} = require('crypto');

randomBytes(256, (err, buf) => {
  if (err) throw err;
  console.log(`${buf.length} bytes of random data: unique random ID ${buf.toString('hex')}`);
});

了解更多

 let count = 0; let previous = 0; const generateUniqueId = () => { const time = new Date().getTime() count = time > previous ? 0 : (++count) const uid = time + count previous = uid return uid }

这是当前解决方案的一个基准,请参阅nanoid benchmark

import { v4 as uuid4 } from 'uuid'
import benchmark from 'benchmark'
import shortid from 'shortid'

let suite = new benchmark.Suite()

suite
  .add('crypto.randomUUID', () => {
    crypto.randomUUID()
  })
  .add('nanoid', () => {
    nanoid()
  })
  .add('uuid v4', () => {
    uuid4()
  })
  .add("math.random", () => {
    (new Date()).getTime().toString(36) + Math.random().toString(36).slice(2)
  })
  .add('crypto.randomBytes', () => {
    crypto.randomBytes(32).toString('hex')
  })
  .add('shortid', () => {
    shortid()
  })
  .on('cycle', event => {
    let name = event.target.name
    let hz = formatNumber(event.target.hz.toFixed(0)).padStart(10)

    process.stdout.write(`${name}${pico.bold(hz)}${pico.dim(' ops/sec')}\n`)
  })
  .run()

结果是

node ./test/benchmark.js
crypto.randomUUID         13,281,440 ops/sec
nanoid                     3,278,757 ops/sec
uuid v4                    1,117,140 ops/sec
math.random                1,206,105 ops/sec
crypto.randomBytes           280,199 ops/sec
shortid                       30,728 ops/sec

测试环境:

  • 2.6 GHz 6 核 Intel Core i7 MacOS
  • 节点 v16.17.0

对我来说,获得唯一 ID 的最简单方法是time ,我在该示例中使用hash

const hash = require('object-hash');
const user = { ..., iat: Date.now() }
const user_id = hash(user)

console.log(user_id) // ex. 49686bab1a2276e0b1bd61ccc86f8156

这就是我在任何方面实际获得唯一标识符的方式。 因为在现实世界中时间永远不会重复。

 const uniqueId = self.crypto.randomUUID(); console.log(uniqueId)

  • Crypto 接口的 randomUUID() 方法用于使用加密安全随机数生成器生成 v4 UUID。
  • 返回包含随机生成的 36 个字符长的 v4 UUID 的字符串。
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;
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM