Postman not getting response from POST - javascript

Using Express/Node and Postgres ('pg' package).
Code:
const createEvent = (request, response) => {
console.log(request.body);
const {
type,
location,
current_attendees,
total_attendees,
details,
event_date,
has_car,
has_food,
cover_charge,
contact_email,
} = request.body;
pool.query(`INSERT INTO events (type, location, current_attendees, total_attendees, details, event_date, has_car, has_food, cover_charge, contact_email) VALUES ('${type}', '${location}', ${current_attendees}, ${total_attendees}, '${details}', TO_DATE('${event_date}', 'YYYY-MM-DD'), ${has_car}, ${has_food}, ${cover_charge}, '${contact_email}')`),
(error, results) => {
if (error) {
throw error;
}
console.log(results);
response.status(201).send('Event created');
}
}
Route:
router.post('/events', db.createEvent);
The object gets inserted into the database just fine and I get the request body's console log, but I don't get the results console log and no response is sent back to postman. It just times out.
I'm sending a normal JSON object (Body -> Raw -> Text -> JSON).
Any idea what's going on? Thanks.

In short - when your code runs it get's to pool.query(...) line (which is async function) and it does not wait for the response, because you haven't specified that you want to wait for it.
Solution would be to make createEvent function async:
const createEvent = async (request, response)
and wait for DB response:
await pool.query(...)
Read more about async/await and/or Promises

I see that the url it's http:localhost:8080/api/events you added the /api to the route, or is a sub router in express

Related

Res.send sends an empty object, even though console.log shows it isn't empty?

I am trying to use the google-sheets api with express and don't have much experience with javascript. I'm attempting to use pass a json object from express to react, but it seems that whenever I finally send the object, it just renders as empty on the frontend?
I've tried using res.body/res.data, but the object doesn't seem to have either. I've also tried to put as many awaits as I can everywhere to make sure the object is loaded in before sending, but nothing seems to do the trick. If I use res.json or res.send with just the response object, I get a circular structure converting to JSON error. Here is the code I'm working with.
async function docShit() {
// Initialize the sheet - doc ID is the long id in the sheets URL
const doc = new GoogleSpreadsheet(
"--SPREADSHEET ID--"
);
// Initialize Auth - see https://theoephraim.github.io/node-google-spreadsheet/#/getting-started/authentication
await doc.useServiceAccountAuth({
// env var values are copied from service account credentials generated by google
// see "Authentication" section in docs for more info
client_email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
private_key: process.env.GOOGLE_PRIVATE_KEY,
});
await doc.loadInfo(); // loads document properties and worksheets
const sheet = doc.sheetsByTitle[--WORKSHEET TITLE--];
const rows = await sheet.getRows(); // can pass in { limit, offset }
return rows;
}
app.get("/home", async (req, res) => {
try {
await docShit()
.then((response) => {
res.send(Promise.resolve(response)); //console log shows the object, but res.send just sends nothing??
})
.catch((err) => console.log(err));
} catch (err) {
console.error(err.message);
}
});
There is no res.send at all in your code. Also, you use await and .then together, but I consider them alternatives. Try the following:
app.get("/home", async (req, res, next) => {
try {
var response = await docShit();
console.log(response);
/* If response is circular, decide which parts of it you want to send.
The following is just an example. */
res.json(response.map(function(row) {
return {id: row.id, cells: row.cells.map(function(cell) {
return {id: cell.id, value: cell.value};
};
})};
} catch (err) {
console.error(err.message);
next(err);
}
});

"Cannot set headers after they are sent to the client" error after post request

need help with some weird error
this is express , nodejs service that hosted on heroku
this is my route controller code
async function PopupConroller(req, res) {
let credential = req.credential;
let zoho_token = null;
console.log('res :>> ', res);
try {
zoho_token = await axios.post(`https://accounts.zoho.com/oauth/v2/token?client_id=${credential.client_id}&client_secret=${credential.client_secret}&refresh_token=${credential.refresh_token}&grant_type=refresh_token`);
console.log('zoho_token.data :>> ', zoho_token.data);
} catch (error) {
console.log('ex 2 :>> ',error);
}
console.log('res :>> ', res);
res.status(200).json({status:"ok"});
return;
}
when service received request, code throws this error
(no error from axios.post request)
the response back : 200 OK with no body
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:530:11)
at ServerResponse.header (/app/node_modules/express/lib/response.js:771:10)
at ServerResponse.json (/app/node_modules/express/lib/response.js:264:10)
at PopupConroller (/app/voicenter.js:261:28)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
when removing those lines everything is ok
response: 200 OK with {status:"ok"}
async function PopupConroller(req, res) {
let credential = req.credential;
let zoho_token = null;
console.log('res1 :>> ', res);
try {
//zoho_token = await axios.post(`https://accounts.zoho.com/oauth/v2/token?client_id=${credential.client_id}&client_secret=${credential.client_secret}&refresh_token=${credential.refresh_token}&grant_type=refresh_token`);
//console.log('zoho_token.data :>> ', zoho_token.data);
} catch (error) {
console.log('ex 2 :>> ',error);
}
console.log('res2 :>> ', res);
res.status(200).json({status:"ok"});
return;
}
in the first example,
When I checked the res object (console.log res1) the headers not sent, but in the second (console.log res2) I noticed that the response headers sent back.
WAY THIS LINE SENT THE HEADERS???
*need to say that similar code in other routes work prefect
zoho_token = await axios.post(`https://accounts.zoho.com/oauth/v2/token?client_id=${credential.client_id}&client_secret=${credential.client_secret}&refresh_token=${credential.refresh_token}&grant_type=refresh_token`);
appreciate the help...
thanks
I am just guessing here, is that what you want?
To expand on the snippet code below, you get the error cannot set headers after they are sent to the client because axios.post() is making the HTTP post request.
In your code, you make an HTTP call via axios so the headers get sent out.
After that, the JS parser continues the evaluation of the code and after the try block, because there is no error, it evaluates the res.status() for a response that has been already sent, hence the error.
So, to solve this issue, you can handle the post request as you do, without resending the response again to the client. You can then "do something" with the promise response within the ´thenable´ function.
If you want to post an optional object via axios, you can do this by passing the argument into the post request.
async function PopupConroller(req, res) {
let credential = req.credential;
let zoho_token = await axios.post("whatever", {"cat": "meaows"})
.then((response)=> {
// do something with the response
})
.catch((err) => console.log(err))
}

Loop through array of Mongoose data

I'm trying to fetch an array of data from Mongoose, loop through the array and add an object to Three.js scene for each item in array.
When I try to render the scene in the browser I'm getting an error saying:
"client_world.js:37 Uncaught (in promise) TypeError: data is not iterable at getData"
However when I console log the data in the get request querying the database, it prints all of the data entries as an array, sp they must be iterable.
I think maybe the data is not arriving to the javascript file.
Here is the code to get the data from the db:
const indexVR = (req, res) => {
Upload.find({})
// .populate('Upload')
.exec(function (err, docs) {
if (err) res.send(err)
// docs.toString()
res.json(docs)
console.log(docs)
})
};
this function is in the following get req:
router.get('/indexvr', FileCtrl.indexVR);
This is the code snippet from the js file:
getData()
async function getData() {
const response = await fetch('/api/indexvr');
const data = await response.json;
console.log(data)
for (item of data) {
try {
scene.add( cube );
} catch (e) {
console.error(e)
}
}
}
nothing in logging to the console in the getData function, however the browser is reading some kind of empty json object.
.. Does anyone know what I'm doing wrong?
Your issue may be as simple as calling the .json method as opposed to referencing it.
Referring to this document: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch .json is a method of the response object returned from fetch.
Try using const data = await response.json();

Stripe Charge promise doesn't resolve

I'm making an AJAX call from StripeCheckout.configure({ }) on the token parameter, like this:
StripeCheckout.configure({
...,
token: function(stripeToken) {
$.post( url, {
// post data
}, function(data) {
console.log("data", data);
return data;
});
}
});
At the URL which receives the AJAX call (let's call it /charge), I have this code:
const charge = (req, res) => {
const {
// get AJAX post data, e.g amount, description, STRIPE_TOKEN, etc
} = req.body
return stripe.charges.create({
amount: amount,
currency: 'gbp',
source: STRIPE_TOKEN,
description: description,
})
.then((charge) => {
const {params} = charge // get various parameters from the successful charge data to be passed into book()
return book(params) // promise function which goes to an external provider
.then((data) => {
return data // data returns from book and is then lost between here and the original AJAX callback
})
}).catch((err) => {
console.log(err)
})
}
as you can see from the comments, the data in the charge function is correct, but then between that promise and the original AJAX call, it's lost and the AJAX call gets nothing. If I look at the network request in Chrome devtools, it says that charge received the data but the AJAX call times out as it receives no response data.
I think I've been looking at this too long and have probably made a super easy and stupid mistake.
Figured this out with help from #Bergi in the comments (thanks Bergi!).
Here is the code that worked for me, sending the update from the promise back to the original Ajax request:
const charge = (req, res) => {
// rest of the promise
.then((data) => {
res.json(data)
})
}).catch((err) => {
console.log(err)
})
}
The reason for this is essentially, the AJAX request is hitting the page (/charge in my case), doing the work to get the data, but returning it does nothing, as, just like in a front-end app, unless you are doing something with it (assigning to a variable, running another function with that data, etc), it will get lost. It needs to be outputted to the page, in JSON format, so the request can see it.

Can't set headers after they are sent after first request only

i'm having a specific problem with the error "Can't set headers after they are sent".
The code is this one:
create: (request, response, next) ->
socket = #app.socket
#
# This method will be used to call the right method inside
# the emails service.
data = JSON.stringify(
Object.assign request.body.data, method: 'server'
)
socket.send data
socket.on 'message', (result) =>
result = JSON.parse(
result.toString()
)
if result.code is 'success'
#model.insertAsync request.body
.then (result) ->
response.json data: result
return
.catch next
return
return
I'm using two servers and socket connection to communication between them. When i want create a email, i send a message for this other server and wait for the result, if the result is "success", i send the data back (i'm using Ember, so i need send the data after saving it). Now the problem: when i send the email for the first time everything works normal, when i try for the second time, a error message shows in my terminal:
Error: Can't set headers after they are sent.
According to express, the error is in this line:
response.json data: result
or in JS:
response.json({data: result});
The code in pure JS:
create: function(request, response, next) {
var data, socket;
socket = this.app.socket;
data = JSON.stringify(Object.assign(request.body.data, {
method: 'server'
}));
socket.send(data);
socket.on('message', (function(_this) {
return function(result) {
result = JSON.parse(result.toString());
if (result.code === 'success') {
_this.model.insertAsync(request.body).then(function(result) {
response.json({
data: result
});
})["catch"](next);
}
};
})(this));
}
Thanks in advance, guys!
Most likely what is happening is you are receiving more than one successful "message" and so it's calling response.json() multiple times.
You could fix this by changing on('message') to once('message') so that the event handler only executes once. However, if that one message is not successful, a response won't be sent. So you may need to either add an else to your if (result.code === 'success') or leave on('message') and introduce some sort of guard variable so that the code inside the if is only executed once.

Categories