前言:
前天开始已经换了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;
后记:
只是用这个例子记录下,有些东西并不是很难,只要愿意去想 ,去发现,还是能够有所进步的。