I have an endpoint (using express) which requires me to do some fetching first. Once a parse the response and use res.send I get an error res.send is not a function.
I tried searching for this error but all searches show users had res,req in the wrong order. In this case, mine appear to be right.
Why is it res is not scope after a convert my response to JSON?
router.post("/customerID", async (req, res) => {
return fetch({endPoint}, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Flowspace-Auth": {myToken},
},
body: JSON.stringify({
query: `query {
user {
name
organizationId
}
}`,
}),
})
.then((res) => {
res.json().then((data) => {
console.log(data) // This works
res.send({ data: data }); // res.send is not a function... why, is it not scoped correctly?
});
})
.catch((err) => console.log("unable to fetch:", err));
});
Your outer response variable is overwritten by your inner result variable. JS goes from the inner most scope to outer most looking for variable. Since, res is already defined in the then clause, that res is used.
Changing it to resp should work.
router.post("/customerID", async (req, resp) => {
return fetch({endPoint}, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Flowspace-Auth": {myToken},
},
body: JSON.stringify({
query: `query {
user {
name
organizationId
}
}`,
}),
})
.then((res) => {
res.json().then((data) => {
console.log(data) // This works
resp.send({ data: data }); // resp will belong to outer response
});
})
.catch((err) => console.log("unable to fetch:", err));
});
You probably want to send something in the catch part too.
You are calling send method on the response of the fetch api call on which the send method is not available. find the correct code below.
router.post("/customerID", async (req, res) => {
return fetch(
{ endPoint },
{
method: "POST",
headers: {
"Content-Type": "application/json",
"Flowspace-Auth": { myToken },
},
body: JSON.stringify({
query: `query {
user {
name
organizationId
}
}`,
}),
}
)
.then((response) => {
response.json().then((data) => {
console.log(data); // This works
res.send({ data: data });
});
})
.catch((err) => console.log("unable to fetch:", err));
});
Related
I am trying to set up an edit feature to edit a post. Right now I am trying to update a specific post by ID and then I'll make it dynamic.
I can get axios to send the PUT request but I don't receive any indication that it is received on the router. Also the ID I have set it showing up correctly in the URL.
I'm not sure how to send the data over to the router so it can find the ID.
Edit component
function handleSubmit(event){
event.preventDefault()
axios ( {
url: `/api/${props.data[0]._id}`,
method: 'PUT',
headers: { "Content-Type": "multipart/form-data" },
id: props.data[0]._id
})
.then(() => {
console.log(`data has been sent to the server from axios: ${props.data[0]._id}`)
})
.catch(() => {
console.log('Data could not be sent from axios')
})
}
Router
router.put('/:id', async (req, res) => {
try {
const updatedGratitude = await PostGratitude.findByIdAndUpdate(req.params.id)
res.status(200).json(updatedGratitude)
} catch (err){
next(err)
}
})
if you are editing a post then you should send the data in the request as well
like a title: "" and description: "" or something and in the in the router, you could write something like this :
function handleSubmit(event) {
event.preventDefault()
axios({
url: `/api/${props.data[0]._id}`,
method: 'PUT',
headers: { "Content-Type": "application/json" },
data: {
title: '',
description: ''
}
})
.then((response) => {
console.log(response)
})
.catch((err) => {
console.log(err)
})
}
you need to pass the arguments as to what to update as well, here is an example of a code that I wrote
router.put('/updatentry/:id',fetchuser, async (req, res) => {
var success = false
try {
const { title, description } = req.body
let newentry = { title: title , description: description
}
let old_entry = await Journal.findById(req.params.id);
if (!old_entry) {
return res.status(404).send({ success, error: 'Not Found'})
}
const update_entry = await Journal.findByIdAndUpdate(req.params.id, { $set: newentry }, { new: true })
return res.send(res: update_entry)
} catch (error) {
return res.status(500).send(error: 'Internal Server Error')
}
})
This is because you forgot the update body on method. Try this:
PostGratitude.findByIdAndUpdate(req.params.id, req.body)
instead of :
await PostGratitude.findByIdAndUpdate(req.params.id)
Because mongoose can not know what to update :D
So I am making a request to an API endpoint. When I print JSONBody which is the variable data passed to POSTRequest(), I get the JSON I created printed to the log, however when I then try and JSON.Stringify() it, I get returned an empty object?
Was just wondering what I am doing wrong and how to fix it :)
getFileData()
const getFileData = () => {
var data = {}
// DO SOME STUFF HERE TO data
POSTRequest(data);
}
POSTRequest()
const POSTRequest = async (JSONBody) => {
console.log(JSONBody)
console.log(JSON.stringify(JSONBody))
try {
const response = await fetch(API_ENDPOINT, {
method: 'POST',
body: JSON.stringify(JSONBody),
headers: { 'Content-Type': 'application/json' }
});
response.json()
.then(function (res) {
Promise.resolve(res)
.then(function (finalData) {
console.log(finalData);
props.setData(finalData);
});
});
} catch (error) {
console.log(error);
}
}
You're not waiting for the response from the fetch call correctly, try this:
const POSTRequest = async (JSONBody) => {
console.log(JSONBody)
console.log(JSON.stringify(JSONBody))
await fetch(API_ENDPOINT, {
method: 'POST',
body: JSON.stringify(JSONBody),
headers: { 'Content-Type': 'application/json' }
}).then((response) => {
console.log(response);
props.setData(response);
}).catch((error) => {
console.log('POSTRequest error: ' + error)
})
});
I am using react.js as frontend and nodejs for the backend. My client-side code is
export const updatePaymentDetails = (userId, token, paymentDetails) => {
return fetch(`${API}/user/${userId}`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Bearer ${token}`
},
body: JSON.stringify(paymentDetails)
})
.then(response => {
console.log(response);
return response.json();
})
.catch(err => console.log(err));
};
And My server-side code is
exports.updateUser = (req, res) => {
User.findByIdAndUpdate(
{_id: req.profile._id},
{$set: req.body},
{new: true, useFindAndModify: false},
(err, user) => {
if(err) {
return res.status(400).json({
error: "You are not authorized to update this user"
});
}
user.salt = undefined;
user.encry_password = undefined;
user.createdAt = undefined;
user.updatedAt = undefined;
console.log(user);
return res.json(user);
}
);
};
Front-end output
In the server-side code, you can see that I am returning the res.json. but On the client-side, I am not getting the value that I have returned from the server.
Please, can anyone help me?
You need to add one more then(). when you call response.json() it also returns a promise apply a then call when you return response.json()
I currently have the below code that works. It makes 8 API calls in order to create a row and insert data into 8 different tables. I would like to refactor it to 1 API call, which makes all the necessary queries at one time.
The only difference in each fetch below is the table name.
createQuestions() {
fetch(
API_URL + `/interview/create/questions/${this.state.lastEmployeeId}`,
{
method: "PUT",
body: JSON.stringify({
lastEmployeeId: this.state.lastEmployeeId,
table: "audit_general",
}),
headers: { "Content-Type": "application/json" },
}
)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
.then(
fetch(
API_URL + `/interview/create/questions/${this.state.lastEmployeeId}`,
{
method: "PUT",
body: JSON.stringify({
lastEmployeeId: this.state.lastEmployeeId,
table: "audit_culture",
}),
headers: { "Content-Type": "application/json" },
}
)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
)
.then(
fetch(
API_URL + `/interview/create/questions/${this.state.lastEmployeeId}`,
{
method: "PUT",
body: JSON.stringify({
lastEmployeeId: this.state.lastEmployeeId,
table: "audit_performance",
}),
headers: { "Content-Type": "application/json" },
}
)
.then((res) => {
if (!res.ok) {
throw new Error();
}
return res.json();
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
)
.then( etc, etc, etc,
I suppose instead, I should be able to run multiple queries through this route with just one call instead?
app.put("/interview/create", function (req, res) {
const employee = req.body.employee;
const employment_level = req.body.employment_level;
const audit_id = req.body.audit_id;
console.log(`employee: ${employee}`);
console.log(`employment_level: ${employment_level}`);
console.log(`audit_id: ${audit_id}`);
connection.getConnection(function (err, connection) {
connection.query(
`INSERT INTO audit_interview (employee, employment_level, audit_id)
VALUES (?, ?, ?)`,
[employee, employment_level, audit_id],
function (error, results, fields) {
if (error) throw error;
res.json(results);
console.log(`Interview has been created`);
connection.release();
}
);
});
});
My main problem is that this works locally fine. But online in my production environment, I keep getting 502 and 503 calls, which seem to be caused by too many calls too close together. I thought maybe reducing my calls as much as possible would be a good thing anyway.
I am trying to do two post requests in JavaScript (client-side), but the second one seems to run before the first one is completed.
This is the code I have:
Client-side code:
$.post("/startGame", {username: username});
$.post("/lookingForAPlayer", {});
Server-side code:
var idPlayer;
app.post('/startGame', function(req, res) {
const idPlayerProm = new Promise((resolve, reject) => {
dbConnection.getIdPlayer(req.body.username).then(data => {
resolve(data)
});
});
Promise.all([idPlayerProm]).then(data => {
idPlayer = data[0];
console.log("idPlayer1: " + idPlayer) //Here idPlayer has a value
const gamePromise = new Promise((resolve, reject) => {
dbConnection.addGame(idPlayer).then(data => {
resolve(data);
});
});
Promise.all([gamePromise]).then(data => {
idGame = data[0];
});
})
});
app.post('/lookingForAPlayer', function(req, res) {
console.log("idPlayer2: " + idPlayer); //Here idPlayer is undefined
});
Result:
As you can see, it even prints idPlayer2 at first when should be printed after idPlayer1.
I am guessing I need to do some sort of Promise in the client side, but I am not sure how as I am new at doing them on the client-side.
Any help?
Update for #DanMossa (I cannot get the value I send from the server with his/her answer).
app.post('/startGame', function(req, res) {
dbConnection.getIdPlayer(req.body.username).then(data1 => {
dbConnection.addGame(data1).then(data2 => {
res.end(JSON.stringify([data1, data2]));
});
});
});
app.post('/lookingForAPlayer', function(req, res) {
//Here I will also res.end() as I do in /startGame.
});
Working off of #Yousaf 's post, using async/await might make it easier to mentally visualize.
try {
const res = await fetch('/startGame', {
method: 'POST',
body: JSON.stringify({ username: username }),
headers: { 'Content-Type': 'application/json' },
});
await fetch('/lookingForAPlayer', {
method: 'POST',
body: JSON.stringify({}),
headers: { 'Content-Type': 'application/json' },
});
} catch (error) {
console.log(error);
}
You can use promise chaining along with fetch api
fetch('/startGame', {
method: 'POST',
body: JSON.stringify({username: username}),
headers: { 'Content-Type': 'application/json' }
})
.then(res => {
// do something with response
// make second request
return fetch('/lookingForAPlayer', {
method: 'POST',
body: JSON.stringify({}),
headers: { 'Content-Type': 'application/json' }
});
})
.then(res => { /* do something with response */ })
.catch(err => console.log(err));
Keep in mind that second POST request will be sent only after first POST request is successful and client has received the response from the server