简体   繁体   中英

Express render external Json to jade

I have a file (api.js) which when I call in terminal using node.js it gives a working JSON response. I've used request-promise to do the http request and the app is an Express boilerplate.

Now I'd like to add that response to a Jade file and have Jade iterate the JSON results.

How do I get express to use this file and then pass it to jade?

Secondly but not essential, how would I get a button in Jade to do a POST request using the same api or how does the front end call the backend and display results in the front end?

Here is my api file api.js:

var rp = require('request-promise');

var initGet = {
  uri: 'http://www.jsonapi.com/get',
  method: 'GET',
  headers: {"Content-Type": "application/json"}
};

var initPost = {
  uri: 'http://www.jsonapi.com/post',
  method: 'POST',
  headers: {"Content-Type": "application/json"},
  data: {},
  resolveWithFullResponse: true
};

var apiCall = function apiCall(options) {
// if request is GET
  if (options.method === 'GET') {
    rp(options)
      .then(function (res) {
        /// I assume this is where the response is sent to jade
      })
      .catch(console.error);
  }
// if request is POST
  else {
    rp(options)
      .then(function (res) {
        /// I assume this is where the response is sent to jade
      })
      .catch(console.error);
  }
};

var apiGet = function apiGet() {
  apiCall(initGet);
};

var apiPost = function apiPost(input) {
  initPost.data = input;
  apiCall(initPost);
};

// example of data in POST
apiPost({
  user: 2,
  event: 'World Cup 2018',
  name: 'Brazil'
});

module.exports = {
  apiGet: apiGet,
  apiPost: apiPost
};

and in the jade file I have:

extends layout
block content
  .title
    h1
      | App
  .ui
    each val in res
    .ui_box
      .ui_box__inner
        .event
          span val.event
        .name
          span val.name
      .drop
        p show drop down
        .arrow
    .ui_box.dropdown
      .submit-button
        p submit
        //submit POST

Here is my solution after much trial and error!!!

I went ahead and used request for my http call to the external jSON api.

api.js:

var request = require('request'); // require in request
var initGet = {uri: 'http://linkToApi.com/get'};
var initPost = {uri: 'http://http://linkToApi.com/post'};

var apiCaller = function (url, cb) {
  //use request to make the external http call to the JSON api
  request({
    url: url,
    json: true
  }, function (error, response, body) {

    if (!error && response.statusCode === 200) {
      cb(body);// Send body/response to callback
    }
  })
};
// Call the api with a call back
var apiGet = function(cb) {
  return apiCaller(initGet.uri, cb);
};

var apiPost = function(post, cb) {
  return apiCaller(initGet.uri + post, cb);
};
// Export the functions for external access
module.exports = {
  apiGet: apiGet,
  apiPost: apiPost
};

now for the express route:

var api = require('./api');
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  //call the api apiGet and create callback function
  api.apiGet(function (data) {
    // render to the index.jade and pass the data from api call
    res.render('index', { result :data});
  });
});

and finally in the index.jade file:

block content
  .ui
//*** make sure the indentation is correct 'for' otherwise it doesn't parse!!
    for data in result //iterate through the results
      .ui_box
        .ui_box__inner
          .event
            span #{data.event} // here pick out the jSON you require
          .name
            span #{data.name}

I'm not 100% sure if I fully understand your question but I'll give it a go.

You wouldn't "get express to use this file and then pass it to jade" as you put it, you would just render a jade file with some data on a request to the server. That request could use your module if you wanted it to, but phrasing it this way helps with the concepts behind it.

For info on how to use templating engines with express read this: http://expressjs.com/guide/using-template-engines.html

And your endpoint will look something like this:

var yourModule = require('./modules/yourModuleFile'); //note you don't need .js

app.get('/', function (req, res) {
  yourModule.apiGet().then(function(result){
    res.render('yourTemplate', result);
  })
})

After writing that example I think you might have a slightly different idea of how to actually use promises. You don't "do the work" inside your module you "return the promise that resolves with the result".

If you need more explanation on this last point just let me know and i'll expand my answer.

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