前言:
前天开始已经换了V7,VSCODE,准备开撸Koa2,koa-generator 直接生成Koa2的样板项目了,然后各种熟悉API。在项目启动时果断一排红字”koa deprecated Support for generators will been removed in v3“,KoaV3将移除generator函数。由于Node Current 7.0 的发布,我们可以直接 runtimeArgs添加:–harmony-async-await 支持async。node一波更新要炸,据说V8最近的更新将会推动async迅速稳定。

正文:
因为不想用CO模块和generator直接安装了Koa@2,然后有个convert中间件能够保证CO和generator这两种方案可以继续运行(ps:目前大量包还木有更新),具体支持列表看这里 https://github.com/koajs/koa/wiki。
首先,先考虑折腾session那里,于是下载了Koa-session,以及Koa-session-mongo。(PS:最后才知道koa2不支持),各种折腾各种报错,在群里猫神的帮助下,终于找到了koa-session2这货,下载了V6+版本的免bable版本后终于跑起来了。由于用redis做持久化,之前的中间件都是自己集成了,这货官方给出了写法,然后我就去翻koa-session2的模块目录。我靠,尽然能看懂,也不是很麻烦啊。于是贴码吧。
每次客户新建对话,后端新建session就会设置cookie,客户端发送cookieNmae(Uid),服务端就能找到对应的讯息。
关于SESSION持久化: 之前在群里问中间件问题的时候,有人反问为什么要持久化。其实除了不可预料的宕机之外,还能防止HttpSession炸内存。还有就是node单线程的问题,多个实例共享session的最佳解决方案就是通过数据库持久化。
//index.js
"use strict";
const Store = require("./libs/store.js");
module.exports = (opts = {}) => {
opts.key = opts.key || "koa:sess";
opts.store = opts.store || new Store();
return (ctx, next) => {
//获得cookie
let id = ctx.cookies.get(opts.key, opts);
let promise = Promise.resolve();
let old = {};
if(id) {
promise = opts.store.get(id).then(session => {
ctx.session = session;
// check session should be a no-null object
if(typeof ctx.session != "object" || ctx.session == null) {
ctx.session = {};
}
});
} else {
ctx.session = {};
}
return promise.then(() => {
old = JSON.stringify(ctx.session);
return next();
}).then(() => {
// no modify
if(old == JSON.stringify(ctx.session)) return;
return Promise.resolve().then(() => {
// destory old session
if(id) {
id = null;
return opts.store.destroy(id);
}
}).then(() => {
if(ctx.session && Object.keys(ctx.session).length) {
// set new session
return opts.store.set(ctx.session, Object.assign({}, opts, {sid: id})).then(sid => {
//创建cookie
ctx.cookies.set(opts.key, sid, opts)
});
}
});
});
}
};
临时session
//store.js
"use strict"
const uid = require("uid-safe");
class Store {
constructor() {
this.session = {};
}
decode(string) {
if(!string) return "";
let session = "";
try{
//存在session
session = new Buffer(string, "base64").toString();
} catch(e) {}
return JSON.parse(session);
}
encode(obj) {
//滚成buffer
return new Buffer(obj).toString("base64");
}
getID(length) {
//获得Uid
return uid.sync(length);
}
get(sid) {
return Promise.resolve(this.decode(this.session[sid]));
}
set(session, opts) {
opts = opts || {};
let sid = opts.sid;
if(!sid) {
//Uid
sid = this.getID(24);
}
this.session[sid] = this.encode(JSON.stringify(session));
return Promise.resolve(sid);
}
destroy(sid) {
delete this.session[sid];
return Promise.resolve();
}
}
module.exports = Store;
结合Redis持久化数据(PS:TTL没写我知道了。。)这是官方的栗子,可以看出持久化也是很方便的能够完成。
const Redis = require("ioredis");
const Store = require("koa-session2/libs/store");
class RedisStore extends Store {
constructor() {
super();
this.redis = new Redis({
port: 6379,
host: '127.0.0.1',
family: 4,
password: '',
db: 0
});
}
async get(sid) {
let data = await this.redis.get(`SESSION:${sid}`);
return JSON.parse(data);
}
async set(session, opts) {
if(!opts.sid) {
opts.sid = this.getID(24);
}
await this.redis.set(`SESSION:${opts.sid}`, JSON.stringify(session));
return opts.sid;
}
async destroy(sid) {
return await this.redis.del(`SESSION:${sid}`);
}
}
module.exports = RedisStore;
后记:
只是用这个例子记录下,有些东西并不是很难,只要愿意去想 ,去发现,还是能够有所进步的。
