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

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

如何设置一个变量值与数据库查询回调? 我如何可以做到这一点?

453092 次浏览

安装NPM uuid包(来源:https://github.com/uuidjs/uuid):

npm install uuid

并在你的代码中使用它,例如ES6导入:

import { v4 as uuidv4, v6 as uuidv6 } from 'uuid';


uuidv4();
uuidv6();

或者使用CommonJS需要:

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


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

我已经有一段时间没有使用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
})

我在2年左右没有编写任何node/js,也没有测试过这个,但基本思想应该保持不变——不要使用繁忙循环,并使用回调。您可能想看一下节点异步包。

编辑:shortid已弃用。维护者建议使用矮小的代替。


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

它非常容易使用:

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

它有一些引人注目的特点:

ShortId创建惊人的短非顺序url友好的唯一 id。完美的url缩短器,MongoDB和Redis id,和任何其他

. Id用户可能看到
  • 默认7-14个url友好字符:A-Z, A-Z, 0-9, _-
  • 非连续的,所以它们是不可预测的。
  • 可以生成任意数量的id而不重复,甚至每天数百万。
  • 应用程序可以重新启动任意次数,没有任何重复id的机会。

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

const crypto = require("crypto");


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


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

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 link

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

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

npm install generate-safe-id

为什么不是uuid ?

Random 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"

更容易,没有额外的模块

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

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

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

Date.now().toString(36)

输出:jzlatihl


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

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

输出jzlavejjperpituute

我正在使用以下,它是工作良好加上没有任何第三方依赖。

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


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

这里的解决方案是旧的,现在已弃用: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。这种实现还应该减少算术溢出,因为不执行任何操作。此外,与字符串相比,它的内存效率更高,因为小数占用的内存比字符串少。

我称之为“Fractional-Unique-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
}

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

矮小的实现了你想要的完全相同的东西。

使用示例:

const { nanoid } = require("nanoid")


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

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

我的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'

从14.17.0开始,你现在可以使用内置的加密模块来生成uuid (UUIDv4 flavour):

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 < / p >

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

我想用这个

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());

生成加密性强的伪随机数据。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')}`);
});


知道更多

你可以使用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

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
}

下面是当前解决方案的一个基准测试,参考矮小的基准

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

测试env:

  • 2.6 GHz 6Cores Intel酷睿i7 MacOS
  • 节点v16.17.0