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

如何设置一个变量值与数据库查询回调?我该怎么做呢?


当前回答

这里是目前解决方案的一个基准,参考纳米基准

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

其他回答

从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

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

让count = 0; 令previous = 0; const generateUniqueId = () => { const time = new Date().getTime() Count = time > previous ?0:(++计数) Const uid =时间+计数 Previous = uid 返回uid }

我已经有一段时间没有使用node.js了,但我想我可能能帮上忙。

首先,在node中,你只有一个线程,并且应该使用回调。你的代码会发生什么,就是这个基础。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,也没有测试过这个,但基本思想应该保持不变——不要使用繁忙循环,并使用回调。您可能想看一下节点异步包。

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

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

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

or

Date.now().toString(36)

输出:jzlatihl


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

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

jzlavejjperpituute输出