一、需求

在使用 express4.x 开发系统的时候,需要利用 session 做信息的闪存服务,用于错误信息的下次页面抛出功能。

这种功能在如 laravel等 PHP 框架基本都是内置的,而 express 则需要自己去实现。

主要做到下面两点:

  • 在 nodejs 的业务代码中,能够 flash session 内容。
  • nunjucks 模板中能顾获取到 flash 的 session 内容,一次性获取。

二、实现

下面所有的中间件均基于 express-session 中间件已经安装的前提下

1、实现闪存 session 的全局中间件

connect-flash 是一个成熟的闪存中间件,实际项目中建议使用该中间件,下面自己实现的中间件仅阐述思想。

闪存信息的中间件原理其实和其他全局中间件功能差不多,主要就是在 req 上挂载一个新的方法如:flash()

_flash() 方法则是借助 express-sessionreq.session 属性将需要保存的数据挂载到 req.session.flash 属性上,以便其他文件获取。

理论上,这里的业务逻辑和安全性应当考虑更多,这里不做多考虑。

module.exports = function flash(){
  return function (req,res,next){
      req.flash = _flash;
      next();
  }
};
/**
 * @name _flash
 * @param {Boolean} type 闪存信息的类型 true/success  false/error
 * @param {String} msg 闪存的信息
 * @private
 */
function _flash(type = false,msg = ''){
    if(msg.length ===0){
        this.session.flash = {};
    }else{
        const status = true;
        this.session.flash = {status,type,msg};
    }
    return this.session.flash;
}

2、实现闪存 session 的获取及模板赋值中间件

由于闪存的 session 信息是需要全局使用的,因此抛出方式,使用的是 req.locals.xxxx = xxxx方式抛出,这样在模板中能够直接获取。

  • if 判断主要是当没有闪存的 session 信息的时候,直接 next()
  • 每次读取到闪存的信息,直接将信息清空,只使用一次。
function sessionFlash(req, res, next) {
    // console.log(req.session.flash);
    if(!req.session.flash) return next();
    res.locals.errStatus = req.session.flash.status;
    req.session.flash.status = false;
    res.locals.errType = req.session.flash.type;
    req.session.flash.type = false;
    res.locals.errMsg = req.session.flash.msg;
    req.session.flash.msg = '';
    next();
}

module.exports = sessionFlash;

3、模板中使用闪存的信息

nunjucks 模板引擎举例,使用的是 layout 布局方式,因此存在一个 base.njk 文件,在这里进行全局信息的获取和处理即可。

showSnacbar 是一个显示错误信息的 js 方法。

逻辑说明:判断是否存在闪存的信息(errStatus),如果存在,则调用插件或者方法。

其中的变量就是第二步中取出且抛在模板上的变量。

{% if errStatus %}
    <script>
        showSnacbar({{ errType }},"{{ errMsg }}");
    </script>
{% endif %}

三、使用

1、中间件注入

  • app.js use session:
  • app.js use flash()
  • app.js use sessionFlashMiddleware
// session and cookie
app.use(cookieParser());
app.use(expressSession({
    secret:'postbird',
    resave:false,
    saveUninitialized:false
}));
// 应用 flash 闪存方法
app.use(flash());
// 全局应用 sessionFlash 中间件
app.use(sessionFlashMiddleware);

2、调用 req.flash()

// 获取文章列表
function getPostList(req,res,next){
    Post.find().then((docs)=>{
       res.docs = docs;
       next();
    }).catch((err)=>{
        req.flash(false,'出现异常,获取列表失败');
        return res.redirect('/admin');
    });
}

四、效果

TIM截图20180522021003.jpg