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); } }) }
有木有人帮一下= =感激不尽
好的,让我们来详细分析并解决这个问题。你需要生成一个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);
}
});
解释
-
类定义:
Session
类包含两个主要方法:get
和createUnionKey
。
-
get 方法:
- 用于从 Redis 中获取指定键的值。
- 如果发生错误,则将错误传递给回调函数。
- 如果没有错误,将获取到的值传递给回调函数。
-
createUnionKey 方法:
- 首先,生成一个长度为 32 的随机字符串。
- 然后,调用
get
方法检查该字符串是否已存在于 Redis 中。 - 如果字符串已存在,递归调用
createUnionKey
方法以生成新的随机字符串。 - 如果字符串唯一(即不在 Redis 中),则将该字符串传递给回调函数。
-
示例使用:
- 创建 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);
}
});
解释:
- generateUniqueKey 方法用于生成一个32位的随机字符串。
- checkAndGenerateKey 方法用于检查生成的字符串是否已经存在于Redis中。如果存在,则递归调用自身以生成新的字符串。
- 设置了一个最大尝试次数(例如1000次),以防止无限递归。
- 使用回调函数
next
返回最终生成的唯一字符串或错误信息。
这样可以确保生成的字符串在Redis中是唯一的,并且不会导致无限递归。