Angular 7 HttpClient: ToPromise does not work with put request - node.js

I'm trying to create an HTTP put request API using express that calls a function upon competition. I successfully got the API calls to update the database but the functions within .then() and .catch() are not being called. Does toPromise() not work for put requests?
On the frontend, I tried adding types to the function and defining it as asynchronous. On the backend, I tried restructuring the .then() and catch() statements. Nothing seems to work.
app.component.ts
public async save(): Promise<any> {
return this.httpClient.put<any>('/api/update-account', {
name: this.name,
email: this.email
}).toPromise()
.then(() => {
// Run if successful put request
success()
})
.catch(() => {
// Run if error
fallback()
})
}
server.js
app.put('/api/update-account', (req, res) => {
let name = req.body.name;
let email = req.body.email;
sql.connect(dbConfig).then(() => {
return sql.query`UPDATE users SET Name=${name} WHERE Email=${email}`
.then(result => {
console.log(result);
sql.close();
}).catch(err => {
console.log(err);
sql.close();
})
}).catch(err => {
console.log(err);
sql.close();
})
});
I expect success() or fallback() to run after the API request, but neither are being called.

You need to return a response using express. For example:
return res.status(200).send('My value');
Because you don't return a response anywhere, nothing is returned to the client.

Related

Empty row on MongoDB data insertion using express.js

I want to add data to my MongoDB collection. I'm getting this data via a local Flask API. I'm GETting the data on my React Frontend and it's displaying fine. I'm not sure why I can't do the same thing on my express nodejs backend. I want to get that same data and use it to build the entity that I'm going to store.
This is how I'm attempting to get the data
app.get('/', async (req, res) => {
let initialData = {};
axios.get('http://localhost:3000/details').then((res) => {
initialData = res.data;
});
const recruit = new RecruitModel({ email:initialData.email,
mobile_number:initialData.mobile_number,
name:initialData.name});
try {
await recruit.save()
res.send("inserted data")
} catch (error) {
console.log(error)
}
})
I'm pretty sure something wrong there and nowhere else. Because if I pass static information instead it's correctly stored, no issues.
You are saving to the database's Recruit Collection before the promise is resolved. Since data to save in the Recruit Collection is dependent upon the result from the API which will initially return the promise, therefore, use promise resolving functions to wait for its result.
Solution#1 (using .then function):
app.get('/', async (req, res) => {
let initialData = {};
try {
axios.get('http://localhost:3000/details').then((response) => {
initialData = response.data;
const recruit = new RecruitModel({
email: initialData.email,
mobile_number: initialData.mobile_number,
name: initialData.name,
});
recruit.save().then((response) => res.send('inserted data'));
});
} catch (error) {
console.log(error);
}
});
Solution#2 (using async await keywords):
app.get('/', async (req, res) => {
try {
const response = await axios.get('http://localhost:3000/details');
const recruit = new RecruitModel({
email: response.data.email,
mobile_number: response.data.mobile_number,
name: response.data.name,
});
await recruit.save();
res.send('inserted data');
} catch (error) {
console.log(error);
}
});
Either solution will work in your case.

Promise not returning resolve from express app.get Nodejs

I'm trying to return a resolve or reject depending on if the promise was successful or not. I can't seem to figure out why this isn't returning the response. All I get from my promise is [object Object]. This is what I get in response.
Here's the code:
app.get('/', (req,res) => {
return new Promise((resolve,reject) => {
var sql = "INSERT INTO usersinfo (firstname,lastname,email,number,latitude,longitude) VALUES(?,?,?,?,?,?)";
conn.query(sql,[fname,lname,email,num,req.query.latitude,req.query.longitude], (err,result) => {
if (err) {
res.send('error')
console.log(err,'there has been an error')
reject('There was an error')
return
}else{
console.log('inserted')
resolve({ success:'true' })
}
res.end()
})
})
})
Where I'm fetching the url:
const res = await fetch(`http://MYIPADDRESS?latitude=${latitude}&longitude=${longitude}`)
console.log(res)
I don't seem to get what's wrong. And if I attach the then((response) => console.log(response)) method I get an error in the expo app saying There was an error sending log messages to your development environment PrettyFormatPluginError:value.hasOwnProperty is not a function. (In 'value.hasOwnProperty('tag')','value.hasOwnProperty is undefined)
You don't need to create a promise. The send method can be called asynchronously -- when the response is ready:
app.get('/', (req,res) => {
var sql = "INSERT INTO usersinfo (firstname,lastname,email,number,latitude,longitude) VALUES(?,?,?,?,?,?)";
conn.query(sql,[fname,lname,email,num,req.query.latitude,req.query.longitude], (err,result) => {
if (err) {
res.send('error');
console.log(err,'there has been an error');
} else {
res.send({ success:'true' }); // <---
console.log('inserted');
}
});
});
NB: also, there is no need to call res.end() as res.send() already implies that.
On the client side you'll have to await the JSON content to be generated:
const response = await fetch(`http://MYIPADDRESS?latitude=${latitude}&longitude=${longitude}`);
const result = await response.json(); // <---
console.log(result);

React.js + Node.js - Error when responding from server. "UnhandledPromiseRejectionWarning: Error: Request failed with status code 304"

As the title suggest, I get a weird error when responding with data from my server.
In homepage.js (which I want to load after loggin in) I have this request to the server to get the posts and then set the posts to the response.
useEffect(() => {
//userService.getDashboard() === Axios.get('http://localhost:3001/homepage')
userService.getDashboard().then((response) => {
setListOfPosts(response)
});
}, []);
This request first goes to the homepage.js, which further sends a request to getPosts, like so:
const headers = req.headers;
const getPosts = Axios.get('http://localhost:3001/getPosts', {headers: headers});
getPosts.catch((response) => {
//NEVER GET ANY RESPONSE???
console.log('Error in homepage.js')
//res.send(response);
});
getPosts.then((response) => {
//NEVER GET ANY RESPONSE???
res.send(response.data);
});
And lastly in the chain I have the getPosts router which does:
router.get('/', authenticateToken, async (req, res) => {
await db.query('SELECT * FROM posts',
(err, result) => {
if (err) {
console.log('HELLO FROM ERROR')
res.send({errorMessage: err});
} else {
console.log(result)
res.send(result);
}
});
});
So I can confirm that after every request to homepage I get all the way to getPosts() and the database query always works fine and goes into the result where "console.log(result)" lies and I can confirm that the result is indeed all the posts. The weird stuff happens when I'm sending back the data. So from getPosts() I'm obviously doing a res.send(result) which sends the data back to homepage.js. But this is when I get the error "UnhandledPromiseRejectionWarning: Error: Request failed with status code 304"
Any idea why?
you should not use res.send inside the .then of axios
this code works for me
useEffect(() => {
getPosts.then((response) => {
console.log("inside getPosts.then ");
console.log(response);
});
and this is my controller file to send request to backend:
const axios = require("axios");
export const getPosts = axios.get("http://localhost:5000/tasks/taskscheck");
getPosts.catch((response) => {
console.log("Error in homepage.js");
});
getPosts.then((response) => {
console.log("inside then get posts");
console.log(response);
});
I have tasks project and I can see in the response all my tasks.

React-Redux Axios Call does not return the same data as my Postman call

I'm currently working on an API call that works exactly the way it was intended within Postman, but when the same call is made on the front-end browser, it does not return the same data. Stack is MERN.
The very interesting part in all of this is that Axios request returns a different array of data each and every time. To help explain this, for testing purposes the database has only 4 messages to return when making the call. In Postman, all 4 messages are returned each and every time. But with React-Redux, the Axios call sometimes returns 2 messages, somtimes returns 3 messages, but never returns the full 4 messages as expected.
Edit:
Looks like this is a useEffect issue, I created a button that calls the same API request and all 4 messages are returned. Anyone else ever had this issue?
Here is the API call:
router.get('/all', auth, async (req, res) => {
try {
const lastMessagesArr = [];
const contacts = await Message.aggregate([
{ $match: { user: ObjectId(req.user.id) } },
{ $group: { _id: '$number' } },
]);
// console.log('contacts', contacts);
// console.log('req.user.id', req.user.id);
const getAllLast = async () => {
for (i = 0; i < contacts.length; i++) {
// let shortenedMessage;
let lastMessage = await Message.find({
user: ObjectId(req.user.id),
number: contacts[i]._id,
}).sort({ createdAt: -1 });
lastMessagesArr.push(lastMessage[0]);
// console.log('lastMessage', lastMessage);
}
lastMessagesArr.sort().reverse();
res.json(lastMessagesArr);
// console.log('lastMessagesArr', lastMessagesArr);
};
await getAllLast();
} catch (err) {
console.error(err.message);
res.status(500).json({ msg: 'Server Error' });
}
});
Here is my axios call React-Redux:
export const getAllMessages = () => async (dispatch) => {
try {
const res = await axios.get('/api/messages/all');
console.log('res.data all messages', res.data);
dispatch({
type: SET_ALL_MESSAGES,
payload: res.data,
});
} catch (err) {
const errors = err.response.data.errors;
if (errors) {
errors.forEach((error) => dispatch(setAlert(error.msg, 'danger')));
}
dispatch({
type: MESSAGE_ERROR,
payload: { msg: err.response.statusText, status: err.response.status },
});
}
};
And this is being called on the front-end through a useEffect hook when the component loads:
const AllConvos = ({ getAllMessages, message }) => {
useEffect(() => {
getAllMessages();
}, []);
return (
....
)
Is this a browser issue? (Using Chrome as the browser) Is this an Axios issue? React-Redux Issue? Any help is much appreciated
export const getAllMessages = () => async (dispatch) => {
The above code is a thunked action (a function that returns a function).
The way it works is that instead of an object being dispatched to the store, a function is sent instead. The redux-thunk middleware checks if it is a function and executes it with dispatch.
const dispatch = useDispatch(); // From react-redux
useEffect(() => {
dispatch(getAllMessages());
}, [dispatch]);
The thunked action needs to be dispatched so that it reaches the redux-thunk middleware. Otherwise nothing is there to pick it up.
Figured this out- it was a async/await issue within the useEffect hook. I moved the useEffect hook from the AllConvos component to component that functions as the page of the site and called the useEffect function there. The useEffect function now looks like this:
useEffect(async () => {
await getAllMessages();
}, []);
If I take away the async/await, the prior behavior experienced before is replicated.

Serving a GET request with nested callbacks

I have a generic Node+Express server where I serve GET requests. Some of these GET requests need multiple DB queries which are callbacks.
Here is an example of my code:
GET router:
router.get('/getbalance', function(req, res, next) {
wallet.createNewAddress()
.then(result => {
res.send(result);
})
.catch(err => {
console.log(err);
});
This is the function with callbacks:
async createNewAddress()
{
pool.query(`SELECT ...`)
.then (dbres1 => {
pool.query(`SELECT ...`)
.then(dbres2 => {
(async() => {
var pubkeys = await this.getPublicKeysFromIndexes(wallet.id, index_wallet_1, index_wallet_2, index_wallet_3);
var script = this.generateScript(pubkey1, pubkey2, pubkey3);
})();
})
.catch(e => {
console.log(e.stack);
})
}
})
.catch(e => {
console.log(e.stack);
});
}
I have removed long statements for brevity.
As you can see, I have multiple levels of nested promises.
What is the proper way to handle a request like this? Should I return each promise or should I run everything synchronously using async()?
What I need to do is to return the script at the very middle of the statements. This last call that returns the script is a normal synchronous function.
Appreciate any advice.
Thank you.
I believe using async/await will give you much more readable code, while essentially following the same logic. Of course you will have to be aware that you'll need to add try/catch handler(s) to the code.
If you use async/await you'll end up with something like this:
async function createNewAddress()
{
try {
let dbres1 = await pool.query(`SELECT ...`);
let dbres2 = await pool.query(`SELECT ...`);
var pubkeys = await this.getPublicKeysFromIndexes(wallet.id, index_wallet_1, index_wallet_2, index_wallet_3);
return this.generateScript(pubkey1, pubkey2, pubkey3);;
} catch (err) {
// ok something bad happened.. we could skip this handler and let the error bubble up to the top level handler if we're happy with that approach.
console.error(err);
// Rethrow or create new error here.. we don't want to swallow this.
throw err;
}
}
You can then call as before:
router.get('/getbalance', function(req, res, next) {
wallet.createNewAddress()
.then(result => {
res.send(result);
})
.catch(err => {
console.log(err);
});
Or use an async handler:
router.get('/getbalance', async function(req, res, next) {
try {
let result = await wallet.createNewAddress();
res.send(result);
} catch (err) {
// Also consider sending something back to the client, e.g. 500 error
console.log(err);
};
})

Resources