-
Notifications
You must be signed in to change notification settings - Fork 384
Open
Labels
Description
起因
redis是一个工具,用户管理保存在内存中的数据,常常被应用于缓存等。它有nodejs的使用版本,我想希望通过它来完成登录模块。
思路
大概思路如下:
- 用户登录成功之后,后端利用redis把用户token和id写进内存,并且回传token
- 前端接收到token之后把token写进cookie,这样以后每次请求都会带上cookie
- 在每个请求(除了登录/注册)之前都挂在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. 结果
# 问题 ## 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不正确');
})
不过这种写法重复抛出了错误,太挫,不使用。
