Capture a JSON GET response in a variable? - node.js

I'm using request-promise to get data from an endpoint that I have.
Is it posible to 'capture' a json response in a variable to use it anywhere?
try{
var gamer = '';//variable to capture json data
var options = {
uri: 'http://localhost:4000/gamers/'+gamer._id+'/find',
json: true
};
RequestPromise(options)
.then(function (data) {
gamer = data;//capturing response
})
.catch(function (err) {
console.log("Error saving player data !");
});
.... do something with gamer ....
}catch(err){
res.status(500).send({
message: err.message || 'An error occurred generating player teams !'
});
}
The reason that I need to do this is because actually I don't have access to the database to get that information, so my only option is to consume an API to get information through collections id's.

Your doing a lot of things correctly already. The issue is your gamer variable will get assigned the value you expect first when your promise resolves. There are many ways to skin this cat, but to get you started try performing whatever you want to perform on the gamer variable in .then(), like this:
try{
var gamer = '';//variable to capture json data
var options = {
uri: 'http://localhost:4000/gamers/'+gamer._id+'/find',
json: true
};
RequestPromise(options)
.then(function (data) {
gamer = data;//capturing response
// here is the rigth place perofrm operations on the answer, as this part of the code gets executed after promise reolves. BTW. Then you don't need variable gamer.
})
.catch(function (err) {
console.log("Error saving player data !");
});
// here is not the right place to do something with gamer as this is executed as soon as promise is initialized, not as it resolves. This means your variable will have initial value here
}catch(err){
res.status(500).send({
message: err.message || 'An error occurred generating player teams !'
});
}

Related

res.json or res.send inside foreach loop async await function error: [ERR_HTTP_HEADERS_SENT]: Nodejs

I have been facing this issue in NodeJs for many days. So I am using an array of Ids that will be matched in mongo documents.
Body Request:
{
"applicantIds":
["62e132596e914ded81846231","62a6c630c7f13211aa0a791a","62d6592bf3db4853b0ba1715"],
"userId":"6299ccdaba5dc977068c0a09"
}
I am checking the applicantIds in the loop for their existence in the database using async and await. After that I am submitting the data into another table. sending response back to the developer using res.send()
but it is throwing the error :[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client.
Here is the code inside for each loop
// loop starts
newTestLink.save().then(function (newTestLink) {
questionIdArr = [];
var stageEmail = {
subject: 'Thanks for taking participation',
// content: JSON.stringify(newTestLink),
html:
'<b>Hello, <strong>Candidate</strong>, Your test link is:\n<b>' +
test_url +
'</b></p>',
};
if (
!helper.send_email(applicantEmailId, stageEmail.subject, stageEmail.html)
) {
return res.status(500).send({
message: 'Something went wrong.',
});
} else {
return res.status(200).send({
message: 'link has been sent.',
});
}
});
// Loop ends
how can I send the response back to the postman as I know the issue is whether Response is being called twice or thrice?
Note: as it is an async and await function if I write Res.send() outside the loop. It prints the response before running the whole function.

Nodejs response and console

I am creating a NodeJS API using Express, PostgreSQL in which I created a controller function which will check the user from the database.
const checkUser = async (req, res) => {
try {
const user = await pool.query('select * from users where email = $1', [req.body.email]);
if (user.rows.length === 0) throw new Error('Error Found');
return res.json("User Found");
} catch (e) {
//======= Output at console ========
//Error: Error Found
console.log(e);
//======== Response Object Received From API ==========
// {
// "msg": "Error Found",
// "Error": {}
// }
res.status(400).send({ msg: 'Error Found', Error: e });
}
};
Consider the situation that the user is not found in the Database so from try block the control passes to the catch block.
1- I am not able to get why the Error thrown from the try block to catch block sends back an empty object as a response. Also, at the same time using console.log prints the correct output value in the console.
2- I want a fix so that I can send e as a response to the User.
The problem is that Error objects are not that easy to serialize (which is intentional). This...
try {
throw new Error('Catch me if you can');
} catch(e) {
console.log(JSON.stringify(e)); // {}
}
... just logs {}, the same as for empty object, because Error objects don't have enumerable properties. And in your case, you don't send that object directly - but make it a property of another object sent to client.
However, there are several ways out of this. If you always need your client to get all the details of an Error, cast that to string (as toString() is overridden):
try {
throw new Error('Catch me if you can');
} catch(e) {
console.log(JSON.stringify(e.toString())); // "Error: Catch me if you can"
}
... or use Error object properties - name and message - as separate fields of your response:
res.status(400).send({
name: e.name || 'Anonymous Error',
msg: e.message || 'no message provided'
});
As sub-approach, you might consider choosing your status code based on type of error you have (always sending 404 for 'not founds', for example).

Cannot access Firestore within a HTTP Trigger of Cloud Functions

I need to store my values from the request body to the cloud firestore and sent back the foruminsertdata.Name back in the response. But I am not able to do this.
const functions = require('firebase-functions');
const admin =require("firebase-admin");
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
exports.helloWorld = functions.https.onRequest((req, res) => {
if(req.method === 'POST'){
foruminsertdata = req.body;
db.collection('forum').add({
Name: foruminsertdata.Name,
Description: foruminsertdata.Description,
Heading: foruminsertdata.Heading,
PostedOn: foruminsertdata.PostedOn,
Status: foruminsertdata.Status,
})
.then(ref => {
console.log('Added document with ID: ', ref.id);
return res.status(200).json(
{
message: foruminsertdata.Name
});
})
.catch(err => {
console.log('Error getting documents', err);
});
res.json({
message: foruminsertdata.Status,
});
}
})
I don't know what is happening...Whatever I do I always get the output as
{
message: foruminsertdata.Status,
}
in which "foruminsertdata.Status" has some value that I give
but what I expect the output as
{
message: foruminsertdata.Name
}
Your function is immediately returning foruminsertdata.Status to the client without waiting for the promise from the database operations to resolve. Any function that returns a promise is asynchronous and returns immediately. Execution will continue in the callbacks you attach to it.
I'm not sure why you have two calls to res.json() in your code, but if you want to send a response only after your query completes, you'll remove the second one and just send a response after the query is done. You will probably also want to send a response in the catch callback as well to indicate an error.

Bad Request error in uber api

I've been trying to get the uber price estimates endpoint working, but I'm stuck on an error that leads me to a blank page saying, "Bad Request." The console also says "callback not a function" but I can't seem to find out what is wrong.
My route:
// Get an upfront fare before requesting a ride
app.get('/v1.2/estimates/price', function(request, response) {
// extract the query from the request URL
var query = request.query;
// if no query params sent, respond with Bad Request
if (!query || !query.lat || !query.lng) {
response.sendStatus(400);
} else {
uber.estimates.getPriceForRouteAsync( {
"product_id": "33de8094-3dc4-4ca9-8f67-243275f57623",
"start_latitude": "38.9597897",
"start_longitude": "-94.60699369999999",
"end_latitude": "39.010969",
"end_longitude": "-94.61509899999999"
})
.then(function(res) {
log(res);
})
.error(function(err) {
console.error(err);
});
}
});
Any help is appreciated.
Please check out the README for node-uber. The method does not take a JSON object but the arguments in the method call:
uber.estimates.getPriceForRouteAsync(38.9597897, -94.606994, 39.010969, -94.615098)
.then(function(res) { console.log(res); })
.error(function(err) { console.error(err); });
Also, the product ID is not needed as the /estimates/price endpoint returns an array of estimates for each product.

Handling 503 Error in Express/Node.js especially in TryCatch case

I have a special case for which I want to clear the possible reason for 503 Error. The following code snippet has a catch statement which runs when system is not able to find any results
app.post('/api/fetch/user', function(req, res){
var email = req.body.emailTxt;
db.one('SELECT * FROM users WHERE email=$1', [email])
.then(function(data){
console.log('DATA:', data);
var userCard = { id: data.user_id, name: data.user_name,
email: data.email, regDate: data.date_created };
res.status(200).json({ 'valid': true, '_payload': userCard });
})
.catch(function(error){
if(error.search(/No data returned from the query/im) > 0) // regex case insensitive search and search multiline as source string is multiline
res.status(500).send('Invalid Request Match');
else
res.status(500).send('ERROR: '+error);
})
});
When my API call is made to this API end point and when no result found the control moves in catch() which is fine but quite strangely it returns 503 - Request timeout error.
I have tried to to remove conditions in if() in order to debug but seems like no matter what but the if-else does not seem working in ExpressJs.
Note: Everything works well and also when control stays in .then(). If I remove if,else and keep simple error display/response return then everything works ok. There is nothing special included in my API; it is only one single page script I prepared to test API.
I think you got error in the .catch block.
Try to modify the code and see if this helps:
app.post('/api/fetch/user', function(req, res){
var email = req.body.emailTxt;
db.one('SELECT * FROM users WHERE email=$1', [email])
.then(function(data){
console.log('DATA:', data);
var userCard = { id: data.user_id, name: data.user_name,
email: data.email, regDate: data.date_created };
res.status(200).json({ 'valid': true, '_payload': userCard });
})
.catch(function(error){
console.error(error); //never ignore errors!
try {
//i think error is an Error Object here, so it doesn't have .search function
if(error.search(/No data returned from the query/im) > 0) // regex case insensitive search and search multiline as source string is multiline
res.status(500).send('Invalid Request Match');
else
res.status(500).send('ERROR: '+error);
} catch (err) {
console.error(err);
res.status(500).send('some unknown error');
};
});
});
Edit: Sorry, removed .finally because you may send response twice.
Edit, better approach to handle error in .catch block.
//make catch block error safe to make sure no error occurs
if (error && error.message == 'No data returned from the query.') {
res.status(500).send('Invalid Request Match');
} else {
res.status(500).send('ERROR: '+error);
}
We use response codes in ExpressJs quite intensively when creating an API service. So it seems a right way that we make use of them directly instead of doing if-else in catch().
Hence, the right way would be:
.catch(function(error){
console.log('ERROR:', error);
res.status(204).send('No Content; Invalid Request Match');
})
However, If you want to display/return detailed message you can do that as well. You can check: http://expressjs.com/en/api.html#res for details on ways you can response back. You can render an HTML template, or return JSON response or even multiline text.
I don't know why if-else creates problem but you can go other way around.
In your specific case the error does not have .search() method attached to it. So better to parse it to string first using .toString();.

Resources