Nodejs 递归回调创建唯一值问题

Nodejs 递归回调创建唯一值问题

我的需求是想用redis自己做一个session模块,随机生成一个32位的字符串。如果判断这个值在redis中有的话,则递归调用接口重新生成一个。确保唯一性 部分代码

//根据key获取redis值 Session.prototype.get = function(key,next){ this.client.get(key,function(err,value){ if(err) next(err); next(null,value); }) }

Session.prototype.createUnionKey = function(next){ console.log(‘createUnionKey’); var str = ‘0123456789abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXYZ’; var length = str.length; var SESSION = ‘’; for( var i = 0;i < 32;i++){ var num = Math.floor(Math.random()*length); SESSION += str.substring(num,num+1); } this.get(SESSION,function(err,value){ if(err) next(err); if(value != undefined ){ Session.prototype.createUnionKey(next);//这个位置应该递归调用这个方法,请问应该怎么写 }else{ next(null,SESSION); } }) }


3 回复

有木有人帮一下= =感激不尽


好的,让我们来详细分析并解决这个问题。你需要生成一个32位的唯一字符串,并且需要确保该字符串在Redis中不存在。如果存在,则需要递归生成新的字符串,直到找到一个唯一的字符串。

以下是改进后的代码示例:

const redis = require('redis');

class Session {
    constructor(client) {
        this.client = client;
    }

    // 根据key获取redis值
    get(key, next) {
        this.client.get(key, (err, value) => {
            if (err) return next(err);
            next(null, value);
        });
    }

    // 创建唯一32位字符串
    createUnionKey(next) {
        console.log('createUnionKey');
        
        const str = '0123456789abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXYZ';
        const length = str.length;
        let SESSION = '';

        for (let i = 0; i < 32; i++) {
            const num = Math.floor(Math.random() * length);
            SESSION += str[num];
        }

        this.get(SESSION, (err, value) => {
            if (err) return next(err);

            if (value !== null) {
                // 如果字符串已存在于Redis中,则递归调用createUnionKey
                this.createUnionKey(next);
            } else {
                // 如果字符串唯一,则返回该字符串
                next(null, SESSION);
            }
        });
    }
}

// 示例使用
const redisClient = redis.createClient();
const sessionManager = new Session(redisClient);

sessionManager.createUnionKey((err, uniqueKey) => {
    if (err) {
        console.error('Error:', err);
    } else {
        console.log('Unique Key:', uniqueKey);
    }
});

解释

  1. 类定义

    • Session 类包含两个主要方法:getcreateUnionKey
  2. get 方法

    • 用于从 Redis 中获取指定键的值。
    • 如果发生错误,则将错误传递给回调函数。
    • 如果没有错误,将获取到的值传递给回调函数。
  3. createUnionKey 方法

    • 首先,生成一个长度为 32 的随机字符串。
    • 然后,调用 get 方法检查该字符串是否已存在于 Redis 中。
    • 如果字符串已存在,递归调用 createUnionKey 方法以生成新的随机字符串。
    • 如果字符串唯一(即不在 Redis 中),则将该字符串传递给回调函数。
  4. 示例使用

    • 创建 Redis 客户端实例。
    • 实例化 Session 对象。
    • 调用 createUnionKey 方法,传入回调函数处理结果。

通过这种方式,你可以确保每次生成的字符串都是唯一的,并且能够递归地生成新的字符串直到找到一个唯一的值。

在你的需求中,你需要生成一个唯一的32位字符串,并确保它在Redis中是唯一的。如果发现字符串已经在Redis中存在,则需要递归地生成新的字符串,直到找到一个唯一的值。

下面是改进后的代码示例:

const redis = require('redis');

class Session {
    constructor(client) {
        this.client = client;
    }

    get(key, next) {
        this.client.get(key, function (err, value) {
            if (err) return next(err);
            next(null, value);
        });
    }

    createUnionKey(next) {
        console.log('createUnionKey');
        const str = '0123456789abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXYZ';
        const length = str.length;
        const SESSION = '';
        const generateUniqueKey = () => {
            let key = '';
            for (let i = 0; i < 32; i++) {
                const num = Math.floor(Math.random() * length);
                key += str[num];
            }
            return key;
        };

        const checkAndGenerateKey = (attempt) => {
            const key = generateUniqueKey();
            this.get(key, (err, value) => {
                if (err) return next(err);
                if (value === null) {
                    // 如果key不存在,则返回这个唯一的key
                    next(null, key);
                } else {
                    // 如果key已存在,则递归检查直到找到一个唯一的key
                    if (attempt > 1000) { // 设置一个递归的最大尝试次数,防止无限递归
                        return next(new Error('Failed to generate unique key after multiple attempts'));
                    }
                    checkAndGenerateKey(attempt + 1);
                }
            });
        };

        checkAndGenerateKey(1);
    }
}

// 示例使用
const client = redis.createClient();
const session = new Session(client);

session.createUnionKey((err, uniqueKey) => {
    if (err) {
        console.error('Error:', err);
    } else {
        console.log('Generated unique key:', uniqueKey);
    }
});

解释:

  1. generateUniqueKey 方法用于生成一个32位的随机字符串。
  2. checkAndGenerateKey 方法用于检查生成的字符串是否已经存在于Redis中。如果存在,则递归调用自身以生成新的字符串。
  3. 设置了一个最大尝试次数(例如1000次),以防止无限递归。
  4. 使用回调函数 next 返回最终生成的唯一字符串或错误信息。

这样可以确保生成的字符串在Redis中是唯一的,并且不会导致无限递归。

回到顶部