2016-11-15 6 views
0

Ich versuche, einige Variablen in die Ansicht zu laden, um breite Menüs zu erstellen, um dynamische Menüs zu erstellen. Ich habe eine neo4j Datenbank auf der Rückseite, die alle Menüstrukturen behält und ich auf ihn über APOC zugreife (die hackish Cypher Queries ignorieren, die ich Daten in der Chiffre strukturiere, die ich vermutlich tun sollte.Express JS Dynamische app.local/res.local Variablen

My erste Lösung war nur ein la die eine Funktion app.locals und nennen es in der Ansicht zuweisen.

//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 

, die offensichtlich nichts getan, weil ich data von der Asynchron query.exec().then() Kette bin Rückkehr konnte ich nicht herausfinden, wie async von einer Ansicht zu behandeln.Ich dachte, dass Funktionen, die in app.locals gespeichert werden, syncronous sein sollten, das APOC nicht auch freundlich ist und nicht ideal für Datenabfragen ist ow. Und so gewickelt ich mit dem Follow-up, das funktioniert aber nicht ideal:

//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 

Dies wird auf jeder Seite jede Abfrage für jedes Menü aufzurufen, und zwar unabhängig davon, ob das Menü auf der Seite ist oder nicht. So ist meine Frage:

Gibt es eine Weise, die ich die erste Version bekommen, wo ich die Funktion in der Ansicht Arbeits nennen, oder gibt es eine andere elegante Lösung, die sicher nur die Funktionen machen, die von den Ansichten benötigt werden gerendert wird aufgerufen?

Am Ende des Tages spielt der Overhead keine große Rolle, weil es nur für einen internen Prototyp-Job ist. Aber ich bin mir sicher, dass es da draußen eine elegante Lösung gibt, und es wäre großartig, wenn ich es so umstrukturieren könnte, dass ich eine Funktion wie getMenu('cat-menu') aus den Ansichten aufrufen könnte, um eine Reihe von Funktionen in app.locals zu speichern.

Ich bin mir sicher, dass es irgendwo eine einfache elegante Lösung gibt, aber ich bin zum ersten Mal seit einiger Zeit wieder im asynchronen Knoten-Netzwerk und ich bin ratlos.

Antwort

0

Ich habe gelernt, React und die Flux-Architektur zu verwenden. Es ist mehr oder weniger für das, was ich erreichen wollte, wo Express Vanilla Renderer nicht gut dafür ausgestattet ist.