How to make response data available outside the function - node.js

Data received from the server is written into variable cols. But it is empty in the output. I'm not sure if cols has now a proper value and is available to work with.
app.post('/get_columns', function (req, res, next) {
var cols = '';
var httpreq = http.request(options, function (response) {
response.on('data', function (chunk) {
cols += chunk;
console.log("body: " + cols);
});
});
httpreq.write(options_data);
httpreq.end();
console.log('cols: '+cols);
});
What output shows:
cols:
body: {"ResultSet Output":[{"NAME": "PART_COL1"},{"NAME": "PART_COL2"}],"StatusCode": 200,"StatusDescription": "Execution Successful"}

HTTP Calls are asynchronous call in Node.js and the response comes as multiple chunks through Events. When you are dealing
with HTTP request in Node.js, you have to deal with "data" & "end"
events on the response object given by HTTP.
Below examples shows how you can deal with the response in HTTP:
app.post('/get_columns', function (req, res, next) {
var cols = '';
var httpreq = http.request(options, function (response) {
// This event is triggered multiple times whenever a chunk is available.
response.on('data', function (chunk) {
cols += chunk;
});
// This event is triggered once when all the chunks are completed.
response.on('end', function (chunk) {
console.log("body: " + cols);
});
});
httpreq.write(options_data);
httpreq.end();
});
Another organized way to handle
var fetchCols = function (options, options_data) {
return new Promise((resolve, reject) => {
var cols = '';
var httpreq = http.request(options, function (response) {
// This event is triggered multiple times whenever a chunk is available.
response.on('data', (chunk) => {
cols += chunk;
});
// This event is triggered once when all the chunks are completed.
response.on('end', () => {
resolve(cols);
});
});
// This event is triggered when there is any error.
httpreq.on('error', (e) => {
reject(e);
});
httpreq.write(options_data);
httpreq.end();
});
};
app.post('/get_columns', function (req, res, next) {
fetchCols(options, options_data)
.then((cols) => {
console.log('body: ', cols);
})
.catch((err) => {
console.error('ERR: ', cols);
});
});

Related

Node.js higher-order function

I am trying to send a http request when an event is entering, but the console outputs in the higher-order function are not working.
exports.handler = async (event) => {
const req = https.get('https://test.com', (res) => {
console.log('statusCode:', res);
console.log('headers:', res.headers);
let data = "";
res.on('data', (d) => {
data += d;
});
res.on('end', () => {
let url = JSON.parse(data);
console.log(url);
});
}).on('error', (e) => {
console.error(e);
});
return 0;
};
Happy for every help i can get!
I updated the code snippet you provided,
const https = require('https');
const func = async () => {
const req = https.get('https://test.com', (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
let data = "";
res.on('data', (d) => {
data += d;
});
res.on('end', () => {
console.log({data})
let url = JSON.parse(data);
console.log(url);
});
}).on('error', (e) => {
console.error(e);
});
return 0;
};
func();
console.log('statusCode:', res.statusCode);
is the correct way to retrieve statusCode from res.
let url = JSON.parse(data);
data is not json, it cannot be parsed
res is an instanceOf IncomingMessage
https://nodejs.org/dist/latest-v14.x/docs/api/all.html#http_class_http_incomingmessage
Have a look at the documentation to understand what is passed on the events emitted
Run the updated code so that you can see what is logged to stdOut

how get data to object when call api use https.request in nodejs

i try get data to variable 'results' when call an api another but unidentified
let results;
const req = https.request(options, (res) => {
res.setEncoding('utf8');
res.on('data', (body) => {
results = JSON.parse(body).payUrl;
});
res.on('end', () => {
console.log('No more data in response.');
});
});
console.log(results);
results = unidentified
In https.request(options,(res)=>{}) res is a stream and will emit data in chunk on event 'data'. So you won't get complete data in one go. You change code something as bellow:
let results;
let url;
const req = https.request(options, (res) => {
res.setEncoding('utf8');
let body="";
res.on('data', (chunk) => {
body = body+chunk // aggregate data
})
res.on('end', () => {
// once data is completly fetched do JSON.parse();
console.log('No more data in response.')
results = JSON.parse(body);
console.log(results)
url = results.url
console.log(url);
})
});
req.on('error', (e) => {
// listen for error
console.log(e.message);
});
Also,https.request(options,(res)=>{}) is async call so console.log(results) in your code will be executed even before api calls complete.

In NodeJs 8.* how do I apply Async / Await on http.get?

The following code gets the result asyncronously from the specified url, and I would like to return parsed variable out of getData method, after I receive the data, making use of async/await in nodejs version 8.* (without callback function).
function getData(v, r) {
var path = 'http://some.url.com';
var parsed = "";
http.get({
path: path
}, function(res) {
var body = '';
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
parsed = JSON.parse(body);
// now I would like to return parsed from this function without making use of callback functions, and make use of async/await;
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
return parsed;
};
Any help is greatly appriciated.
First off let me say I recommend using the npm package request to deal with http gets, that said.
1.) Use a Promise (await does this in the background)
function getData(v, r) {
var path = 'http://some.url.com';
var parsed = '';
return new Promise((resolve, reject) => {
http.get({
path: path
}, function(res) {
var body = '';
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
parsed = JSON.parse(body);
resolve(parsed);
});
}).on('error', function(e) {
reject(e.message);
});
});
};
Then usage would be
getData(v, r)
.then(success => console.log(success))
.catch(error => console.log(error))
2.) or callbacks You could pass in a callback as a parameter to getData (i.e. getData(v, r, callback)) then within the body of your function call it via callback(parsed) or callback(error_msg).
Then usage would be:
getData(v, r, result=>console.log(result))
or easier to read maybe:
function callback(res) {
console.log(res)
}
getData(v, r, callback)

Using Q library for HTTP api response testing in nodejs

how to use Q to make it wait until previous response has come from the server.
What I am looking to do here is compare the response from test server and production server for the same request.
I get the responses back from both the servers, but unable to compare them since the assert statement is executed before the response comes back.
Any one know what I am doing wrong. heres the code.
var Q = require('q');
var path='';
var prodResponse = '';
var tstReponse = '';
Q.fcall(readFile())
.then(secondFunction())
.then(thirdFunction())
.then(function(){
console.log("prodResponse: "+prodResponse);
console.log("tstResponse: "+tstResponse);
assert.strictEqual(prodResponse, tstResponse)
})
.catch(function(){
console.log('error occurred');
})
.done();
function readFile(){
fs.readFile('hostname.json', function (err, data) {
if (err) return console.error(err);
path = JSON.parse(data);
return JSON.parse(data);
});
}
function secondFunction(){
var prodOptions = {
hostname: 'somehostname.com',
port: 80,
path: "/path?"+path.path,
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
auth : ''
};
return http.request(prodOptions, function(res) {
console.log('Prod');
res.setEncoding('utf8');
res.on('data', function (chunk) {
prodResponse = chunk;
return chunk;
});
res.on('end', function() {
console.log('No more data in response.');
})
}).on('error', function(e) {
console.log('problem with request: ' + e.message);
}).end();
}
function thirdFunction(){
// same a second, only difference is the response http.
}
There is multiple errors in your code
Q.fcall(readFile())
Your q variable is q and not Q. So this line will crash because Q is undefined (javascript is case sensitive).
Then, readFile doesn't return any promise (in fact, it returns nothing). So the q library can't use anything to wait the end of any asynchronous work. The then callbacks will be fired immediatly.
You can use Q.ninvoke to make your readFile function return a promise, and you can use Q.defer to create and return a promise from your secondFunction:
var Q = require('q');
var path='';
var prodResponse = [];
var tstReponse = '';
readFile()
.then(secondFunction())
.then(thirdFunction())
.then(function(){
console.log("prodResponse: "+prodResponse);
console.log("tstResponse: "+tstResponse);
assert.strictEqual(prodResponse, tstResponse)
})
.catch(function(){
console.log('error occurred');
})
.done();
function readFile(){
return Q.ninvoke(fs, 'readFile', 'hostname.json').then(function (data) {
path = JSON.parse(data);
return path;
}, function (err) {
console.error(err);
});
}
function secondFunction(){
var prodOptions = {
hostname: 'somehostname.com',
port: 80,
path: "/path?"+path.path,
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
auth : ''
};
var defer = Q.defer();
var chunks = [];
http.request(prodOptions, function(res) {
console.log('Prod');
res.setEncoding('utf8');
res.on('data', function (chunk) {
chunks.push(chunk);
});
res.on('end', function() {
console.log('No more data in response.');
prodResponse = chunks.join('');
defer.resolve(prodResponse);
})
}).on('error', function(e) {
console.log('problem with request: ' + e.message);
defer.reject(e);
}).end();
return defer.promise;
}
function thirdFunction(){
// same a second, only difference is the response http.
}

I am trying to read image from different server and write on response

function media(req,res){
console.log(req.query.image);
var collectionName = 'imageTable';
var selector = MongoHelper.idSelector(req.query.image);
MongoHelper.findOne(selector, collectionName, function(err, image) {
console.log(image.picture);
var url_parts = url.parse(image.picture);
var options = {host: url_parts.hostname, path: url_parts.pathname};
http.get(options).on('response', function (response) {
var body = '';
var i = 0;
response.on('data', function (chunk) {
i++;
body += chunk;
console.log('BODY Part: ' + i);
});
response.on('end', function () {
console.log('Finished');
res.writeHead(200,{'Content-Type':'image/JPEG'});
res.write(body);
res.end();
});
});
});
}
I am fetching image from different server. I have url of that image. And I am writing the response. But here response image is get corrupted. Any idea about how to write jpeg image in response?
function media(req,res){
console.log(req.query.image);
var collectionName = 'facebook';
var selector = MongoHelper.idSelector(req.query.image);
MongoHelper.findOne(selector, collectionName, function(err, image) {
var url_parts = url.parse(image.picture);
var options = {host: url_parts.hostname, path: url_parts.pathname};
http.get(options).on('response', function (response) {
res.writeHead(200,{'Content-Type':'image/JPEG'});
response.on('data', function (chunk) {
res.write(chunk);
});
response.on('end', function () {
res.end();
});
});
});
}
Here I got the solution. Instead of writing whole data at the end. Write it each time you get and end the response when you reach to the end of file. But still if anyone have better idea can write here.

Resources