解耦 node.js 应用程序中的 Redis 客户端

Dan*_*nte 2 javascript redis node.js express

嗨,我在 node.js 应用程序中使用 redis 进行用户缓存。用户登录后,用户信息被缓存,并在每隔一个请求访问以确定用户具有什么访问权限,客户端基于此接收信息、视图等。现在,该应用程序在开始时创建了一个 redisClient 并将其传递给所需的快速路由回调(几乎是所有回调)。老实说,我真的不喜欢到处传递的额外参数 - 特别是当它相同时。有没有更好的方法来做到这一点,例如,如果我在每个模块中初始化 redisClient 是否会有额外的开销

var express = require('express'),
    loginFunctionality = require('./routes/login'),
    homeFunctionality = require('./routes/home')
    ...

// Connect to redis
var redisClient = redis.createClient();
redisClient.on("error", function(err){
    console.log("An error occurred with redis:" + err);
});
... 


app.get('/', homeFunctionality.home);

app.post('/register', loginFunctionality.createNewUser);

app.post('/login', loginFunctionality.login(redisClient, secret));
...
Run Code Online (Sandbox Code Playgroud)

我想知道的是,是否有删除 redisClient 参数的好方法。

rob*_*lep 7

您可以通过中间件将客户端与每个请求一起传递:

// initialization
var client = redis.createClient(...);

app.use(function(req, res, next) {
  req.redis = client;
  next();
});

// a route handler
app.get('/', function(req, res) {
  req.redis.get(...);
  ...
});
Run Code Online (Sandbox Code Playgroud)

或者,如果适用,您可以创建一个更复杂的中间件,该中间件将自行执行缓存查找并将用户数据与请求一起传递,因此您不必在每个请求处理程序中执行查找。

或者您可以将 Redis 客户端初始化移动到一个单独的模块,并从您需要的每个文件中要求它:

// redis-client.js
var redis = require('redis');
module.exports = redis.createClient(...);

// elsewhere
var client = require('./redis-client');

app.get('/', function(req, res) {
  client.get(...);
  ...
});
Run Code Online (Sandbox Code Playgroud)

添加于 2019 年 1 月 16 日

请记住,使用此技术,如果某些内容(如Ctrl+ C)断开服务器连接,您可以轻松关闭连接,只需添加client.quit().

process.on('SIGTERM', () => {
  if (client) {
    console.log('Ending CACHE connection');
    client.quit();
  }
  console.log('Closing server...');
  app.close(() => {
    console.log('server was closed!');
    process.exit(0);
  });
});
Run Code Online (Sandbox Code Playgroud)

  • 即使你的回调在不同的模块中,它们仍然会被传递给 `req` 对象(我假设),所以它们可以使用 `req.redis`(向 `req` 添加属性是一种将内容向下传播到中间件的好方法/路由链)。第二个示例使用了[模块被缓存](https://nodejs.org/api/modules.html#modules_caching) 在第一次被 `require()` 处理后的事实,因此它们都将共享相同的Redis客户端实例。 (2认同)