0

I'm trying to get 2 APIs into one page using Nodejs and Express. I've been researching of the issue and there comes using Async and Promise but couldn't apply the right fit answer for my code. Is there any ways that I can get data from 2 APIs which are 'url' and 'url_test' to a single page which is 'index.ejs'?

server.js

app.get('/users', function (req, res) {

  var url = apiUrl + '/users' + apiKey,
      url_test = apiUrl + '/projects' + apiKey;

  request.get(url, function (error, response, body) {
      var bodyData = parseJSON(body);
      res.render('index', {
          apiData: bodyData
      });
  });

  request.get(url_test, function (error, response, body) {
      var bodyData = parseJSON(body);
      res.render('index', {
          apiData-test: bodyData
      });
  });

});

index.ejs

<div>
    <% for (var i = 0; i < (apiData.users).length; i++) { %>
        <div><%= (apiData.users[i]).username %></div>
    <% } %>

    <hr>

    <% for (var i = 0; i < (apiData-test.projects).length; i++) { %>
        <div><%= (apiData-test.projects[i]).id%></div>
    <% } %>
</div>

2 Answers 2

1

You need to make both API calls FIRST and then call res.render() when you have the combined results. The most modern way to do that would be to use promises and you can use the request-promise library for that which is a promisified version of the request library you are currently using:

const rp = require("request-promise");

app.get('/users', function (req, res) {

  var url = apiUrl + '/users' + apiKey,
      url_test = apiUrl + '/projects' + apiKey;

  Promise.all([rp({uri: url, json:true}), rp({uri: url_test, json:true})]).then(([apiData, apiData-test]) => {
      res.render('index', {apiData, apiData-test});
  }).catch(err => {
      console.log(err);
      res.sendStatus(500);
  });
});

The json: true option will automatically parse the JSON for you.


In case you didn't know, the request() library and its derivatives are now in maintenance mode and will not be receiving any new features. There is a list of alternatives here. The one I am using is got() and your code using that would be this:

const got = require('got');

app.get('/users', function (req, res) {

  var url = apiUrl + '/users' + apiKey,
      url_test = apiUrl + '/projects' + apiKey;

  Promise.all([got(url).json(), got(url_test).json()]).then(([apiData, apiData-test]) => {
      res.render('index', {apiData, apiData-test});
  }).catch(err => {
      console.log(err);
      res.sendStatus(500);
  });
});
Sign up to request clarification or add additional context in comments.

Comments

0

Since you are doing server side rendering you are sending the front end data (your rendered ejs template) in your api response, so it doesn't really make sense to hit two api endpoints to get data. Instead you should include all of the data that you want in one api call.

1 Comment

The API calls likely belong to some service that the OP doesn't control (they are what they are).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.