I am currently having an issue with figuring out how to wait for the request to finish before returning any data. I do not believe I can do this with a Callback and I have not been able to figure out a good way of using the EventEmitter to do it. The reason I cannot use a callback is because my flow currently works like this.
Request comes into server > Generate XML > Contact remote API for details to finish generating XML > Finish Generating XML > Return request to client
The code I currently have looks very similar to the code included below.
Web Server:
var xml = require('./XMLGenerator');
response.writeHead(200, {'Content-Type': 'text/xml'});
response.write(xml.generateXML());
response.end();
XML Generator:
function generateXML(){
// Code to generate XML
var API = require('./API');
var response = API.getItems("5");
for(var i = 1; i <= response.length; i++)
{
// more code to generate further XML using the API response
}
// Finish generating and return the XML
}
API Grabber:
function getItems(sort_by, amount) {
var request = require("request")
var url = ".json?amount=" + amount;
request({
url: url,
json: true
}, function (error, response, body) {
console.log('we got here!');
if (!error && response.statusCode === 200) {
var items = body.data.items;
console.log(items);
return items;
} else {
console.log("Error connecting to the API: " + url);
return;
}
})
}
When running the code and testing directly it returns "undefined" meaning that the request has not been made yet. I just need to know a way to make the XML generator wait for the request to finish before continuing on with the generation. (there may be minor errors in the psudeo code I typed up as it is not an exact copy paste from the source, it does however work in this flow)
Am I just using bad practices, or is this the correct way that I should be attempting this?
EDIT: The problem is not loading the module/API file, that loads perfectly fine. The problem is that the request takes about 2 seconds to complete, and that node moves on before the request completes.
I am currently having an issue with figuring out how to wait for the request to finish before returning any data. I do not believe I can do this with a Callback and I have not been able to figure out a good way of using the EventEmitter to do it. The reason I cannot use a callback is because my flow currently works like this.
Request comes into server > Generate XML > Contact remote API for details to finish generating XML > Finish Generating XML > Return request to client
The code I currently have looks very similar to the code included below.
Web Server:
var xml = require('./XMLGenerator');
response.writeHead(200, {'Content-Type': 'text/xml'});
response.write(xml.generateXML());
response.end();
XML Generator:
function generateXML(){
// Code to generate XML
var API = require('./API');
var response = API.getItems("5");
for(var i = 1; i <= response.length; i++)
{
// more code to generate further XML using the API response
}
// Finish generating and return the XML
}
API Grabber:
function getItems(sort_by, amount) {
var request = require("request")
var url = "https://url.com/api/get_items.json?amount=" + amount;
request({
url: url,
json: true
}, function (error, response, body) {
console.log('we got here!');
if (!error && response.statusCode === 200) {
var items = body.data.items;
console.log(items);
return items;
} else {
console.log("Error connecting to the API: " + url);
return;
}
})
}
When running the code and testing directly it returns "undefined" meaning that the request has not been made yet. I just need to know a way to make the XML generator wait for the request to finish before continuing on with the generation. (there may be minor errors in the psudeo code I typed up as it is not an exact copy paste from the source, it does however work in this flow)
Am I just using bad practices, or is this the correct way that I should be attempting this?
EDIT: The problem is not loading the module/API file, that loads perfectly fine. The problem is that the request takes about 2 seconds to complete, and that node moves on before the request completes.
Share Improve this question edited May 22, 2015 at 6:41 OstlerDev asked May 22, 2015 at 6:28 OstlerDevOstlerDev 5422 gold badges6 silver badges12 bronze badges 7- i dont get why are not you using the callback ? – ProllyGeek Commented May 22, 2015 at 6:31
- possible duplicate of Node.js - asynchronous module loading – ProllyGeek Commented May 22, 2015 at 6:33
- @ProllyGeek I cannot use the callback because the way that the flow works, the web server is attempting to serve the content immediately. Unless there is a way that I can serve content at a later time then after the immediate request then I have to wait. – OstlerDev Commented May 22, 2015 at 6:33
- please check the duplicate question. – ProllyGeek Commented May 22, 2015 at 6:34
- The problem is not loading the module/API file, that loads perfectly fine. The problem is that the request takes about 2 seconds to complete, and that node moves on before the request completes. – OstlerDev Commented May 22, 2015 at 6:41
2 Answers
Reset to default 8You need to use callbacks. Change your API grabber to this:
function getItems(amount, callback) {
// some code...
request({
url: url,
json: true
}, function (error, response, body) {
// some code...
if (!error && response.statusCode === 200) {
// some code
callback(items); <-- pass items to the callback to "return" it
}
})
}
Then change the xml generator to also accept callbacks:
function generateXML(callback){
// Code to generate XML
var API = require('./API');
API.getItems("5",function(response){
for(var i = 1; i <= response.length; i++)
{
// more code to generate further XML using the API response
}
// Finish generating and return the XML
callback(xml_result); // <-- again, "return" the result via callback
});
}
Then in your server code do:
var xml = require('./XMLGenerator');
response.writeHead(200, {'Content-Type': 'text/xml'});
xml.generateXML(function(xmlstring){
response.write(xmlstring);
response.end();
});
Do these changes since request
is async, use callbacks.
API.getItems("5", function(rs){
var response = rs;
for(var i = 1; i <= response.length; i++)
{
// more code to generate further XML using the API response
}
// Finish generating and return the XML
}
});
...
function getItems(sort_by, amount, callback) {...
...
callback(items); //Instead of return items;
...
You cannot return
from an async
call, which is request
module in your case. In such cases you can either use promises or callbacks
. This is a solution with callback.
The actual problem of it returning undefined
is it doesnot wait for var response = API.getItems("5");
to execute completely and executes the next line and hence you get response
as undefined
. I hope you get the point.\
Also I hope
response.writeHead(200, {'Content-Type': 'text/xml'});
response.write(xml.generateXML());
response.end();
is somewhere inside some callback of an API or http.createServer
.