javascript - nodejs中redis客户端的异步导出
问题描述
下面的代码构造一个redis客户端并导出。我正在从保管库秘密管理服务中获取 redis 密码,并且该调用是一个承诺/异步。代码不会等待该调用,它会在异步调用完成之前导出 redis 客户端。我不确定我在这里做错了什么。任何想法?
import redis from 'redis';
import bluebird from 'bluebird';
import logger from '../logger';
import srvconf from '../srvconf';
import { getVaultSecret } from '../services/vault.service';
const vaultConfig = srvconf.get('vault');
bluebird.promisifyAll(redis);
let redisUrl = '';
const maskRedisUrl = (url) => url.replace(/password=.*/, 'password=*****');
const setRedisUrl = (host, port, pw) => {
const pwstring = pw ? `?password=${pw}` : '';
const url = `redis://${host}:${port}${pwstring}`;
console.log(`Setting redis_url to '${maskRedisUrl(url)}'`);
return url;
}
if (vaultConfig.use_vault) {
(async () => {
const secret = await getVaultSecret(`${vaultConfig.redis.secrets_path + vaultConfig.redis.key}`)
redisUrl = setRedisUrl(srvconf.get('redis_host'), srvconf.get('redis_port'), secret.PASSWORD);
})().catch(err => console.log(err));
} else {
if (!srvconf.get('redis_url')) {
redisUrl = setRedisUrl(srvconf.get('redis_host'), srvconf.get('redis_port'), srvconf.get('redis_password'));;
} else {
redisUrl = srvconf.get('redis_url');
console.log(`Found redis_url ${maskRedisUrl(redisUrl)}`);
}
}
const options = redisUrl
? { url: redisUrl }
: {};
const redisClient = redis.createClient(options);
redisClient.on('error', err => {
logger.error(err);
});
export default redisClient;
解决方案
问题是(async () => {...})()
返回 aPromise
并且您没有await
在顶层使用它,因此脚本继续运行超过该行,设置options = {}
并返回redisClient
.
您需要的是一个顶级 await,默认情况下在Node versions >= 14.8.0
. 但是,如果您的项目使用比该版本更旧的版本,则有一个解决方法,如下所示。
请注意,以下代码未经测试,因为我在本地没有相同的项目设置。
模块
import redis from "redis";
import bluebird from "bluebird";
import logger from "../logger";
import srvconf from "../srvconf";
import { getVaultSecret } from "../services/vault.service";
const vaultConfig = srvconf.get("vault");
bluebird.promisifyAll(redis);
let redisUrl = "";
let redisClient = null;
const initRedisClient = () => {
const options = redisUrl ? { url: redisUrl } : {};
redisClient = redis.createClient(options);
redisClient.on("error", (err) => {
logger.error(err);
});
};
const maskRedisUrl = (url) => url.replace(/password=.*/, "password=*****");
const setRedisUrl = (host, port, pw) => {
const pwstring = pw ? `?password=${pw}` : "";
const url = `redis://${host}:${port}${pwstring}`;
console.log(`Setting redis_url to '${maskRedisUrl(url)}'`);
return url;
};
(async () => {
if (vaultConfig.use_vault) {
try {
const secret = await getVaultSecret(
`${vaultConfig.redis.secrets_path + vaultConfig.redis.key}`
);
redisUrl = setRedisUrl(
srvconf.get("redis_host"),
srvconf.get("redis_port"),
secret.PASSWORD
);
} catch (err) {
console.log(err);
}
} else {
if (!srvconf.get("redis_url")) {
redisUrl = setRedisUrl(
srvconf.get("redis_host"),
srvconf.get("redis_port"),
srvconf.get("redis_password")
);
} else {
redisUrl = srvconf.get("redis_url");
console.log(`Found redis_url ${maskRedisUrl(redisUrl)}`);
}
}
// Initialize Redis client after vault secrets are loaded
initRedisClient();
})();
export default redisClient;
用法
在您导入和使用客户端的所有地方,您始终需要检查它是否实际初始化成功,如果没有,则抛出(并捕获)明确定义的错误。
const redisClient = require("path/to/module");
...
if (redisClient) {
// Use it
} else {
throw new RedisClientNotInitializedError();
}
...
推荐阅读
- python - TypeError:“函数”对象不可下标。致力于基于文本的冒险游戏
- php - Symfony - 在单元测试中检查 isGranted($attribute,$subject)
- javascript - angular中的那些绑定方法有什么区别?
- ibm-cloud - Istio 安装失败
- python - 如何将 pandas.Series 混合字节/字符串转换/解码为字符串或 utf-8
- javascript - 我在首页的名字没有响应
- bash - 替换由行号指定的两行之间的内容
- javascript - 在下一个分页上滚动触发点击事件
- kubernetes - 在本地 Kubernetes 集群中使用 Kafka Exporter 的 HPA
- node.js - 用于 node.js 应用程序的 heroku/python buildpack 被拒绝