I am calling network requests in a forEach loop, each request returns a new object which I would like to push to an array that is outside the forEach. When it is called after awaiting for the network requests to complete, it returns as empty "[]".
return this.get(urlOne, function (error, response) {
if (response.statusCode === 200) {
let array = [];
stores.forEach((store) => {
this.get(urlTwo, function (error, response) {
if (response.statusCode === 200) {
array.push(response.body);
}
});
});
console.log(array);
}
});
This is just a guess but, stores.forEach contents are async thus console.log(array) is called right after stores.forEach() is calle d(not completed) meaning array is blank.
console.log(array); probably needs to be called when the requests are actually done not right after they are made.
Simplest way to test if this is true is to see the array for every push if you see the array growing with your data there is the problem.
return this.get(urlOne, function (error, response) {
if (response.statusCode === 200) {
let array = [];
stores.forEach((store) => {
this.get(urlTwo, function (error, response) {
if (response.statusCode === 200) {
array.push(response.body);
console.log(array);
}
});
});
}
});
(EDIT)
if (response.statusCode === 200)
array.push(response.body);
else if(response.statusCode === 204)
console.log(array);
Status code 204 means No Content, if this isn't being sent automatically or an equivalent, you may need to send it manual some how.
Related
I was called function inside setinterval. But i don't take return value from function.
My code:
function getApiData() {
request({
url : 'http://testest.com',
json : true
}, (error, response , body) => {
if(!error && response.statusCode == 200){
return JSON.stringify(body);
}
else{
return undefined;
}
});
}
Call:
setInterval(() => {
var data = getApiData();
console.log(data);
}, 2000);
Output : Undefined
Please help me. (I am learning new)
As #Aravindan Ve pointed out, there is no way to get retrieve the value returned by that function.So, define a different function
functionPrintResponse(res){
console.log(res)
}
and instead of returning there, invoke functionPrintResponse(JSON.stringify(body))
I have to make multiple serialise call on server side in NodeJs using request module , and RxJs Observable
I have array of Url Address like ['www.google.com','facebook.com']
When I make request to call then server get busy in event loop . I want to know when my last url call gets response so that I can send response to front end
here is my code so far
const foo = Observable.create(function (observer) {
res.writeHeader(200, { "Content-Type": "text/html" });
var str = '<html><head></head><body><h1> Following are the responses: </h1><ul>'
res.write(str);
let count = 0;
addressesArray.forEach(function (element, i) {
observer.next(element);
if (some Condition) {
console.log('here i want to call complete when I get last response')
// observer.complete();
}
})
})
and this is my subscribe function
const subscription = foo.subscribe({
next : addres =>
{
request(addres , function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(response)
}
if (typeof response === "undefined" || typeof body === "undefined") {
console.log('No resp')
}
})
},
complete:()=>{console.log('done')}
})
You can start off your Observable from addressesArray with from operator, it'll complete itself when it reach the end of the array
from(addressesArray).pipe(
mergeMap(address => {
return new Observable(obs => {
request(address, function (error, response, body) {
if (!error && response.statusCode == 200)
obs.next(response)
else
obs.next('')
obs.complete()
})
})
}),
reduce((allResponses, response) => {
return allResponse += '<li>' + response + '<li/>'
}, ''),
tap(allResponses => {
res.writeHeader(200, { "Content-Type": "text/html" });
var str = '<html><head></head><body><h1> Following are the responses: </h1><ul>'
res.write(allResponses + '</ul')
res.end()
})
).subscribe()
I currently have an asynchronous API call that makes at this moment 19 different request to a string end-point using the async & request NPM packages. I just discovered that towards the end of my requests, the actual object that is being returned is the data for the request prior. Here is an example of my code:
router.get('/', function(req, res) {
async.parallel([
function(next) {
request(queryString + 'end point link', function(error, response, body) {
if (!error && response.statusCode == 200) {
var variable0 = JSON.parse(body);
return next(null, variable0);
};
console.log(error);
next(error);
});
},
function(next) {
request(queryString + 'end point link', function(error, response, body) {
if (!error && response.statusCode == 200) {
var variable19 = JSON.parse(body);
return next(null, variable19);
};
console.log(error);
next(error);
});
}],
function(err, results) {
res.render("view", {
variable0: results[0],
variable1: results[1],
variable2: results[2],
......
......
variable19: results[19]
});
});
});
This was working perfectly until I noticed my last three variables (lets call them 17, 18 and 19) were returning the results of the prior API call. I'm unsure why this is occurring, and any advice would be greatly appreciated.
The results variable async provides is an array, which I've modified into an object at a given index for the appropriate request.
Turns out I missed a faulty request in my code. Issue has been solved. Thanks SO.
This question already has answers here:
NodeJS get async return value (callback) [duplicate]
(2 answers)
Closed 5 years ago.
I'm working on a module that returns a the data retrieved from an http request using the request module. However, I'm having a problem when I want to pass the data out of the function. Take this, for example.
function getData(term) {
var parsedData
request.post(url, term, (err, response, body) => {
if (!err && response.statusCode == 200) {
parsedData = doSomethingTo(body);
}
});
return parsedData;
}
This method doesn't work, since the function getData() performs asynchronously and the value is returned before the request can actually return the proper data.
function getData(term) {
var parsedData
request.post(url, term, (err, response, body) => {
if (!err && response.statusCode == 200) {
parsedData = doSomethingTo(body);
return parsedData;
}
});
}
This method doesn't work either, as it will merely make the request function return the parsed data, and not the getData function.
How could I make the parent function return the data parsed from the request function?
use Promise like this :
function getData(term) {
return new Promise(function(resolve){
request.post(url, term, (err, response, body) => {
if (!err && response.statusCode == 200) {
var parsedData = doSomethingTo(body);
resolve(parsedData);
}
});
});
}
and you can call your function like this :
getData(term).then(function(data){
//console.log(data);
})
use the bluebird promise module very fast.
var Promise = require('bluebird');
function getData(term) {
return new Promise(function(resolve,reject){
if (!err && response.statusCode == 200) {
var parsedData = doSomethingTo(body);
resolve(parsedData);
}else{
reject(err);
}
});
};
then the place you are calling the function do this;
var promise = getData(term);
promise.then(function(data){console.log(data)}).catch(function(err){console.error(err)});
I'm trying to send JSON from two urls to one webpage(one that I am creating). It works perfectly when I send one request, but as soon as I add another request it sends an error saying "Can't set headers after they are sent:.
app.get("/service", function(req, res) {
request("http://example.com", function(error, response, body) {
if (!error && response.statusCode == 200) {
var data = JSON.parse(body);
res.render("example.ejs", { data: data });
}
})
request("http://123.com", function(error, response, body) {
if (!error && response.statusCode == 200) {
var data = JSON.parse(body);
res.render("example.ejs", { data: data });
}
})
});
This error happens because you render example.ejs twice this not allowed. I will show you two ways to achieve your goal without any error.
1) This way is a best practice.
// Install request-promise package first using this command below:
npm install request-promise;
// then replace your code with this one below:
app.get("/service", function(req, res) {
var request = require('request-promise');
var data1;
request("http://example.com")
.then(function(data) {
data1 = JSON.parse(data);
return request("http://123.com");
})
.then(function(data) {
data2 = JSON.parse(data);
console.log('data1', data1, 'data2', data2);
res.render("example.ejs", { data1: data1, data2: data2 });
});
});
and second way:
2) This way is bad practice avoid to use callback inside callback, but anyway it works.
app.get("/service", function(req, res) {
request("http://example.com", function(error, response, body) {
if (!error && response.statusCode == 200) {
var data1 = JSON.parse(body);
request("http://123.com", function(error, response, body) {
if (!error && response.statusCode == 200) {
var data2 = JSON.parse(body);
console.log('data1', data1, 'data2', data2);
res.render("example.ejs", { data1: data1, data2: data2 });
}
});
}
});
});
Summary: I suggest you to use 1 way, read this article about promises:
https://strongloop.com/strongblog/promises-in-node-js-with-q-an-alternative-to-callbacks/ and write clean code. I simply explain that promises are tool to avoid callback inside callback.