Express JS Dynamic app.local / res.local变量

时间:2016-11-15 07:40:15

标签: javascript node.js express neo4j pug

我正在尝试将一些变量加载到视图渲染网站范围内以构建动态菜单。我在后端有一个neo4j数据库,它保存了所有的菜单结构,并且我通过APOC访问它(忽略了我正在使用的cypher构建数据的hackish Cypher查询。

我的第一个解决方案是将一个函数分配给app.locals并在视图中调用它:

//app.js
app.locals.catMenuQuery = function(){
  var query = apoc.query(
    'MATCH (c:Category)-[o:CHILD_OF]->(m:Menu {url: "cat-menu"}) \
      OPTIONAL MATCH (c2:Category)-[o2:CHILD_OF]->(c) \
      WITH c, c2, o, o2 \
      ORDER BY o2.order, c2.name \
      WITH \
        { \
          name: c.name, \
          url: c.url, \
          children: collect(c2),\
          order: o.order \
        } AS rows \
      ORDER BY rows.order \
      RETURN collect(rows)'
  );
  query.exec().then(function (qres) {
    var data = qres[0]['data'][0]['row'][0];
    return data;
  }, function (fail) {
    console.log(fail)
  });
}

//view.pug
ul#cat-menu.in
  each cat in catMenuQuery()
    li(class= cat.url)
      h1= cat.name
      ul
        each child in cat.children
          li= child.name

这显然没有做任何事,因为我从异步data链返回query.exec().then()。我无法弄清楚如何处理从视图中调用异步。我认为存储在app.locals中的函数必须是同步的,APOC也不友好,无论如何都不适合数据查询。所以我结束了下面的工作,但不是很理想:

//app.js
app.use(function(req,res,next){
  var query = apoc.query(
    'MATCH (c:Category)-[o:CHILD_OF]->(m:Menu {url: "cat-menu"}) \
      OPTIONAL MATCH (c2:Category)-[o2:CHILD_OF]->(c) \
      WITH c, c2, o, o2 \
      ORDER BY o2.order, c2.name \
      WITH \
        { \
          name: c.name, \
          url: c.url, \
          children: collect(c2),\
          order: o.order \
        } AS rows \
      ORDER BY rows.order \
      RETURN collect(rows)'
  );
  //console.log(query.statements);
  query.exec().then(function (qres) {
    var data = qres[0]['data'][0]['row'][0];
    console.log(util.inspect(data,false,null));
    res.locals.catMenuQuery = data;
    next();
  }, function (fail) {
    //console.log(fail)
    next();
  });
})

//view.pug
ul#cat-menu.in
  each cat in catMenuQuery
    li(class= cat.url)
      h1= cat.name
      ul
        each child in cat.children
          li= child.name

这将调用每个页面上每个菜单的每个查询,无论该菜单是否在页面上。所以我的问题是:

有没有办法可以获得我在视图中调用函数的第一个版本,或者是否有另一个优雅的解决方案可以确保只调用正在渲染的视图所需的函数?

在一天结束时,开销并不重要,因为它只是用于内部原型工作。但我确信那里有一个优雅的解决方案,如果我可以重构它以从视图中调用类似getMenu('cat-menu')的函数来节省一大堆函数({1}},那将会很棒。

我确定在某个地方有一个简单优雅的解决方案,但我有一段时间第一次回到节点异步地带而且我很难过。

1 个答案:

答案 0 :(得分:0)

我开始学习使用React和Flux Architecture。它或多或少都是为了实现我想要实现的目标而设计的,其中Express vanilla渲染器没有很好的装备。