【发布时间】:2016-11-15 07:40:15
【问题描述】:
我正在尝试将一些变量加载到视图渲染站点范围内以构建动态菜单。我在后端有一个 neo4j 数据库,它保留了所有菜单结构,我正在通过 APOC 访问它(忽略我在密码中构建数据的骇人听闻的 Cypher 查询,我可能应该在其中进行。
我的第一个解决方案是将 a 函数分配给 app.locals 并在视图中调用它 a la:
//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
这显然什么也没做,因为我从异步 query.exec().then() 链返回 data。我不知道如何处理从视图中调用异步。我认为存储在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') 这样的函数,以节省在 app.locals 中的一堆函数,那就太好了。
我确信某处有一个简单而优雅的解决方案,但我有一段时间第一次回到节点异步领域,我被难住了。
【问题讨论】:
标签: javascript node.js express neo4j pug