简体   繁体   English

是否可以在快速中间件回调中修改 pug.js 参数 object

[英]Is it possible to modify the pug.js-parameter object in an express middleware-callback

Currently I'm on a legacy application using pug.js as view engine in a node.js express-app.目前我正在使用 pug.js 作为 node.js express-app 中的视图引擎的遗留应用程序。

I want to implement a generic way to display feedback messages.我想实现一种通用的方式来显示反馈消息。 I want to be able to display messages (successes, errors), even if the handler does reply with a redirect.我希望能够显示消息(成功、错误),即使处理程序确实使用重定向进行回复。

This is what I want:这就是我要的:

handlePostRequest(req, res){
  // do stuff with the post request
  doStuff(req.body);

  //This should be done of course somewhere else.
  req.session.successes=req.session.successes|[];

  //save some success-message for the user
  req.session.successes.push("Your post has been saved. Thank you!");

  //but reply with a 302
  res.redirect(req.headers.referer);
}

//a get request. maybe the handler above redirected here
handleGetRequest(req,res){
  // we do NOT get the successes here. Just the 'pure' data.
  const renderData=getRenderData();
  res.render('fancy-pug-template', renderData);
}

fancyMiddlewareForMessages(req, res, next){
  //how to implement getRenderDataByBlackMagic()????
  const renderData = getRenderDataByBlackMagic();
  //set the messages
  renderData.successes = req.session.successes;
  //empty saved messages
  req.session.successes = [];
  next();
}

Obviously, I do not want to polute every handler which actually renders a template with some logic which retrieves the messages and adds them to the parameter object. I would like to move this cross-cutting concern in a middleware callback or something like that.显然,我不想污染每个实际呈现模板的处理程序,这些处理程序具有一些逻辑,这些逻辑检索消息并将它们添加到参数 object。我想在中间件回调或类似的东西中移动这个横切关注点。

So, the question is: Can this be achieved?所以,问题是:这能实现吗? How?如何? I'm fairly new to pug.js, maybe I'm overlooking something obvious.我是 pug.js 的新手,也许我忽略了一些明显的东西。

Ok, I found a way.好的,我找到了一个方法。 This is what I did:这就是我所做的:

const requestStorage = new AsyncLocalStorage<Request>();

function patchRenderFunction(req: Request, res: Response, next: NextFunction) {
  const render = res.render;
  res.render = function (view: string, options?: any, callback?: (err: Error, html: string) => void) {
    const messages = new MessageManager(req);

    //merge errorMessages
    options.errorMessages = mergeMessageArrays(options.errorMessages, messages.errors);
    //same for successMessages
    options.successMessages = mergeMessageArrays(options.successMessages, messages.successes);

    render.bind(this)(view, options, callback);
  };
  requestStorage.run(req, () => {
    next();
  });
}

export function applyAutomaticRenderAttributes(app: Express): void {
  app.use(patchRenderFunction);
}

export function successMessage(message: string, req?: Request) {
  if (!req) {
    req = requestStorage.getStore();
  }
  if (!req) {
    console.error('No request found in async storage. This should not happen. Please report this issue. (successMessage)');
    return;
  }
  new MessageManager(req).addSuccessMessage(message);
}

//export function errorMessage(...) omitted

The MessageManager uses the requests session to store messages. MessageManager 使用请求 session 来存储消息。 It also filters them in some respect.它还在某些方面过滤它们。 I'm using the session because the application runs clustered (thank you, pm2).我正在使用 session,因为该应用程序运行集群(谢谢 pm2)。 Since the session is stored in the db via express-mysql-session , I avoid problems with non-sticky sessions.由于 session 通过express-mysql-session存储在数据库中,我避免了非粘性会话的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM