Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nodejs redis实战--如何写登录模块 #51

Open
youngwind opened this issue Mar 28, 2016 · 0 comments
Open

nodejs redis实战--如何写登录模块 #51

youngwind opened this issue Mar 28, 2016 · 0 comments
Labels

Comments

@youngwind
Copy link
Owner

起因

redis是一个工具,用户管理保存在内存中的数据,常常被应用于缓存等。它有nodejs的使用版本,我想希望通过它来完成登录模块。

思路

大概思路如下:

  1. 用户登录成功之后,后端利用redis把用户token和id写进内存,并且回传token
  2. 前端接收到token之后把token写进cookie,这样以后每次请求都会带上cookie
  3. 在每个请求(除了登录/注册)之前都挂在token校验中间件,如果没有token或者token不正确,则抛出错误,否则进入下一个中间件。

redis基本使用

1. 安装

npm install redis --save

2. 最简单的例子

var redis = require("redis");
var client = redis.createClient();  // 创建redis实例

client.set("name", "youngwind", redis.print);
// 保存数据到内存

client.get("name", redis.print);
// 从内存中读取数据

3. 结果

2016-03-28 4 57 37

# 问题 ## 1. 异步问题

nodejs-redis操作是异步的,而且不原生支持promise,要么写回调函数,要么包一层promise。官方readme里面推荐使用bluebird.

You can also use node_redis with promises by promisifying node_redis with bluebird.

我觉得有点麻烦,而且还有各种then,我希望直接使用co和yield来解决它,所以我找到了co-redis
所以代码就变成了这样

var co = require('co');
var redisClient = require('redis').createClient();
var wrapper = require('co-redis');
var redisCo = wrapper(redisClient);
co(function* () {
  yield redisCo.set('test', 33);
  console.log(yield redisCo.get('test')); // logs 33 
});

2. 错误捕获

判断用户token是否有效的中间件,我一开始是这样写的。

module.exports = function () {
  return function (req, res, next) {
    var token = req.query.token;
    if (is.existy(token)) {
      co(function* () {
        var userId = yield redisCo.get(token);
        if (is.existy(userId)) {
          next();
        } else {
          throw new Error('token不正确');  // 这里不对
        }
      })
    } else {
      throw new Error('没有token');
    }
  }
};

但是有个问题,在抛出错误"token不正确"的时候并没有被错误中间件捕获。后来查了一下原因才发现,co本身会捕获错误,它把这个错误catch住了,所以express捕获不到。解决办法有两个。
1.把错误对象传给next()

if (is.existy(userId)) {
    next();
} else {
    next(new Error('token无效'));
}

2.利用co的catch

co(function* () {
        var userId = yield redisCo.get(token);
        if (is.existy(userId)) {
          next();
        } else {
           throw new Error('token不正确');
        }
      }).catch(function(err){
       throw new Error('token不正确');
})

不过这种写法重复抛出了错误,太挫,不使用。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant