0

I am trying to call multiple external api within for loop but as per the result i am getting only one iteration from the for loop sending the response back.

Yes, its not the right approach to handle multi api request, please suggest the best approach as it has to be sequential req/res

First Request - Call to find respective api. Response holds the data to feed into two api which are called within for-loop.

For-loop Second API Request - feeds data to the third API request.

var express = require('express');
var bodyParser = require('body-parser');
var Request = require("request");

var app = express();
app.use(bodyParser.json());

app.post('/building/', function (req, res) {
	'use strict';

	var myObject = null;

	var callSiteApi = {
		uri: 'http://localhost:8080/site/',
		body: JSON.stringify(req.body),
		method: 'POST',
		headers: {
			'Content-Type': 'application/json'
		}
	}
	// First External API Call
	Request(callSiteApi, function (error, response) {
		if (error) {
			console.log('ERROR with user request.');
			return response.sendStatus(500); // Return back that an error occurred
		} else {
			// Get data from response.body

    
			var materialquerystring = "mat="+response.body.material+"&date="+response.body.date;
            var floor = response.body.floor;

			for (var i = 0; i < floor.length; i++) {

				matereialValueURL = "http://localhost:8080/material/q="+materialquerystring;
				// Second External API Call within for loop
				Request.get(materialValueURL, (error, response, body) => {
					if (error) {
						console.log(req.error);
						
					}
					materialObject = JSON.parse(body);
          var valuequerystring = "value="+materialObject.value;
          // do somehting with materialObject
          
					console.log("first request iteration =" + i);

					sitevalueURL = "http://localhost:8080/value/q="+valuequerystring;
					// Third External API Call within for loop
					Request.get(sitevalueURL, (error, response, body) => {
						if (error) {
							logger.debug('[' + pid + '] ' + req.error);
							//return console.dir(error);
						}
						valueObject = JSON.parse(body);           
            console.log("second request iteration =" + i);
            // do somehting with valueObject 7 materialObject
            var a = materialObject.a;
            var b = valueObject.b;
            var c = a+b;
            
						
					});
				});
			}

			res.writeHead(200, {
				'Content-Type': 'application/json'
			});
			res.end('{"value-1":"a","value-2":"b","value-3":"c","material":"materialquerystring","value":"valuequerystring"}');
		}
	});
});

7
  • 1
    You need to familiarize yourself with how callbacks work. In your first Request's callback, calling return will not work like you think it does, and the response is the one from the API call, not res from your /building/ route handler. And making multiple requests like that isn't going to work with a simple for loop; you'll need Promise.all() for that. Commented Sep 26, 2018 at 7:29
  • thanks, any good example I can refer? Commented Sep 26, 2018 at 7:33
  • 1
    It's going to look something like this: pastebin.com/CuEd6q71 Commented Sep 26, 2018 at 7:41
  • chris, for every for loop two api request are called and do something with the both their response before another iteration. e.g. 2 iteration of for loops will have 2x2=4 external api request. This is where i am getting stuck. With promise I need 2nd & 3rd api localhost:8080/material & localhost:8080/value in for loop. I hope i made sense Commented Sep 26, 2018 at 7:51
  • No, you just call Promise.all() inside Promise.all(). Or you create an array containing all 4 requests, then call Promise.all() on it. Commented Sep 26, 2018 at 7:52

1 Answer 1

2

If you only need to get a number from the user's request, and then issue the same http request that number of times, something like this should do. I brought in a pointfree map helper from crocks to make things a little easier.

You might need to make a few adjustments here and there, particularly in the final then clause

const map = require('crocks/pointfree/map');

const app = express();

app.use(bodyParser.json());

const range = integer => [...new Array(integer).keys()]
const replicate = (i, x) => range(i).fill(x)

const handleError = error => {
  logger.debug(`['${pid}'] ${error.reponse.error}`)
  return error;
}

const getMaterialURIs = response =>
  replicate(response.body.floor.length, `http://localhost:8080/material/q=${response.body.material}`)

const processMaterialResponse = response => {
  doSomethingWithMaterial(response.body)
  return response;
}

const getSiteValueURI = response =>
  `http://localhost:8080/value/q=${response.body.value}`;

const processSiteValueResponse = response => {
  doSomethingWithSiteValue(response.body)
  return response;
}

app.post('/building/', function (req, res) {
  const uri = 'http://localhost:8080/site/';
  const body = JSON.stringify(req.body);
  const method = 'POST';
  const headers = { 'Content-Type': 'application/json' };

  // First External API Call
  Request({uri, body, method, headers})
    // 1: fetch to derive the material URI
    .then(getMaterialURIs)
    // 2: fetch from that material URI
    .then(map(Request.get))
    .then(Promise.all)
    // 3: process the material response
    .then(map(processMaterialResponse))
    // 4: derive the siteValueURI 
    .then(map(getSiteValueURI))
    // 5: fetch the siteValueURI
    .then(map(Request.get))
    .then(Promise.all)
    // 6: process the site value response
    .then(map(processSiteValueResponse))
    .catch(handleError)
    .then(response => {
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end('{"material":"materialquerystring","value":"valuequerystring"}');
    });
});
Sign up to request clarification or add additional context in comments.

8 Comments

thanks benny, can you have a look at the code now i have corrected.
if i understood you correctly, the edited answer should fit your case better
$ node sequence.js D:\sandbox\tax\sequence.js:36 app.post('/building/', function (req, res) { ^^^ SyntaxError: Unexpected identifier @benny-powers
Its working, thanks. But again its iterating only once. The project is I need to find number of floors that's the first api localhost:8080/site. Based on the floors i need to find material and site value for each floor . So I have to put 2nd & 3rd api in loop until no. of floors is exhausted.
The last response should hold few fields from response body/data of 1st, 2nd, 3rd api
|

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.