Rendering view after multiple SELECT queries in Express

后端 未结 2 475
遥遥无期
遥遥无期 2020-12-28 10:48

I\'m a bit new in Node.JS and Express framework and I have a great problem with the code below:

app.get(\'/student\', function(req, res) {
    var dbRequest          


        
相关标签:
2条回答
  • 2020-12-28 11:15

    In your situation, I would split up the database calls into separate calls, and make use of the next middleware function.

    It would looks something like:

    function findStudent(req, res, next) {
        var dbRequest = 'SELECT * FROM Students WHERE IDCard = \'' + req.query['id'] + '\'';
        db.all(dbRequest, function(error, rows) {
            if(rows.length !== 0) {
                req.students = rows;
                return next();
            }
    
            res.render('incorrect_student'); /* Render the error page. */            
        });
    }
    
    function findGroups(req, res, next) {
        dbRequest = 'SELECT * FROM Groups WHERE Name = \'' + req.query['group'] + '\'';
            db.all(dbRequest, function(error, rows) {
                /* Add selected data to previous saved data. */
                req.groups = rows;
                next();
            }
        });
    }
    
    function renderStudentsPage(req, res) {
        res.render('student', {
            students: req.students,
            groups: req.groups
        });
    }
    
    app.get('/student', findStudent, findGroups,  renderStudentsPage);
    

    When you GET /student, you first call findStudent. Once the db call is finished, it will either render an error page, or call next(). Calling next goes to the next function, findGroups, which will then call renderStudentsPage. You can store the data on the req object as you move down the line of functions.

    Hope this helps, and here is more info: http://expressjs.com/guide/using-middleware.html


    edit/note:

    I did not mention it earlier, but if you pass in an argument when calling next(), you will trigger the error handling state. Convention dictates next() is left parameter-less unless you have met an error instance.

    You want to separate out the UI rendering aspect from the database call, so going further, your code could look like:

    function findStudent(req, res, next) {
        var dbRequest = 'SELECT * FROM Students WHERE IDCard = \'' + req.query['id'] + '\'';
        db.all(dbRequest, function(error, rows) {
    
            if (error || !rows.length) {
                return next(error);
            }
    
            req.students = rows;
            return next();
        });
    }
    

    And then elsewhere in your code you can handle rendering error pages.

    0 讨论(0)
  • 2020-12-28 11:16

    I know this is an old question, but for anybody still having problems and using MongoDB instead this is what worked for me.

    //index.js    
    const express = require('express');
    const router = express.Router();
    
    function getData (req, res, next) {
      var db = req.db;
      var collection = db.get('usercollection');
    
      collection.find({}, {}, function(e, docs) {
        req.data = docs;
        return next();
      });
    }
    
    function getVendor (req, res, next) {
      var db = req.db;
      var collection = db.get('usercollection');
    
      collection.distinct("vendor", function(e, docs) {
        req.vendor = docs
        next();
      });
    }
    
    function getType (req, res, next) {
      var db = req.db;
      var collection = db.get('usercollection');
    
      collection.distinct("type", function(e, docs) {
        req.type = docs
        next();
      });
    }
    
    function renderData(req, res) {
        res.render('index', {
            data: req.data,
            vendor: req.vendor,
            type: req.type
        });
    }
    
    /* GET home page. */
    router.get('/', getData, getVendor, getType, renderData);
    
    
    module.exports = router;
    

    Then inside your ejs file

    //index.ejs 
    <body>
    <div id="app">
    <h1>Choose a Vendor</h1>
    <template v-for="vendor in values.vendor">
      <label :for="vendor">{{ vendor }}</label>
      <input type="radio" :value="vendor" v-model="flagpole.vendor">
    </template>
    
    <div>
      <template v-for="type in values.type">
        <label :for="type">{{ type }}</label>
        <input type="radio" :value="type" v-model="flagpole.type">
      </template>
    </div>
    
    </div>
    
    <script type="text/javascript">
    var vendor = <%- JSON.stringify(vendor) %>
    var type = <%- JSON.stringify(type) %>
    
    var vm = new Vue({
      el: '#app',
      data: {
        values: {
          vendor: vendor,
          type: type
        },
        flagpole: {
          vendor: '',
          type: ''
        }
      },
    
    0 讨论(0)
提交回复
热议问题