首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >nodejs中redis客户端的异步导出

nodejs中redis客户端的异步导出
EN

Stack Overflow用户
提问于 2021-04-22 15:25:03
回答 1查看 174关注 0票数 1

下面的代码构建了一个redis客户端并导出。我正在从保管库秘密管理服务中获取redis密码,该调用是promise/async。代码不会等待该调用,它会在异步调用完成之前导出redis客户端。我不确定我在这里做错了什么。有什么想法吗?

代码语言:javascript
复制
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;
EN

回答 1

Stack Overflow用户

发布于 2021-04-22 16:56:30

问题是(async () => {...})()返回一个Promise,而您没有在顶层await它,所以脚本继续运行到该行之后,设置options = {}并返回redisClient

您需要的是在Node versions >= 14.8.0中默认启用的top-level await。但是,如果您的项目使用早于此版本的版本,则有一种解决方法,如下所示。

请注意,以下代码未经过测试,因为我在本地没有相同的项目设置。

模块

代码语言:javascript
复制
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;

用法

在导入和使用客户端的所有地方,您总是需要检查它是否实际初始化成功,如果没有,则抛出(并捕获)一个定义良好的错误。

代码语言:javascript
复制
const redisClient = require("path/to/module");
...
if (redisClient) {
  // Use it
} else {
  throw new RedisClientNotInitializedError();
}
...
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67208618

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档