简体   繁体   中英

Node/Express - use API JSON response to (server-side) render the app

Preamble: I'm new to web dev so maybe this might be a very basic question for you vets.

I'm using MVC architecture pattern for this basic app. I've models (MongoDB), views (Express Handlebars), and controllers (functions that take in req, res, next and returns promises (.then > JSON is returned, .catch > error is returned). I'll be routing the paths reqs to their corresponding api endpoints in the controllers.

This makes sense (right?) when I'm purely working on API calls where JSON is the res. However, I also want to call these api endpoints > get their res.json > and use that to render my HTML using Handlebars. What is the best way to accomplish this? I can create same controllers and instead of resp being JSON, I can do render ("html view", res.json). But that seems like I'm repeating same code again just to change what to do with the response (return JSON or Render the JSON).

Hope I'm making sense, if not, do let me know. Please advise.

ps try to ELI5 things for me. (:

Edit:

//Model Example
const Schema = require('mongoose').Schema;

const testSchema = new Schema({
    testText: { type: String, required: true },
});

const Test = mongoose.model('Test', testSchema);

module.exports = Test;


//Controller Example
const model = require('../models');

module.exports = {
    getAll: function(req, res, next) {
        model.Test.find(req.query)
            .then((testItems) => {
                !testItems.length
                    ? res.status(404).json({ message: 'No Test Item Found' })
                    : res.status(200).json(testItems);
            })
            .catch((err) => next(err));
    },
};

//Route Example
const router = require('express').Router(),
    controller = require('../controllers');

router.get('/', controller.getAll);

module.exports = router;

I want the endpoints to return JSON and somehow manage whether to render (if the req comes from a browser) or stay with JSON (if called from Postman or an API web URL for example) without repeating the code. I'm trying to not create two endpoitns with 99% of the code being the same, the only difference being .then > res.status(200).json(testItems); vs .then > res.status(200).render('testPage', { testItems}).

对于邮递员,您可以在req.headers检查req.headers postman-token的存在,然后您可以相应地进行渲染,如下所示:

req.headers['postman-token'] ? res.json({ /* json */ }) : render('view', {/ * json */});

If you want to go with checking postman token then you can use similar to method1 .

if you want to check with query params in this case you can get json response or html even from browser for future use also and is not dependent on postman then use similar to method2 of the following example.

const express = require('express')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
const port = 5000



app.get('/method1', (req, res) => {
  const isJSONResp = req.headers['postman-token']
  const resp = { status: "hello" }
  if (isJSONResp) {
    res.json(resp)
  } else {
    res.render('some.html', resp)
  }
})

app.get('/method2', (req, res) => {
  const params = req.params
  const resp = { status: "hello" }
  if (params.resp === 'json') {
    res.json(resp)
  } else {
    res.render('some.html', resp)
  }
})

app.listen(port, () => console.log(`Example app listening on port ${port}!`))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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