NodeJS & ReactJS: FormData is not working - javascript

hello i am trying to send data to server but it does not works and returns undefined
here is what i have tried
CLIENT:
var Data = new FormData();
Data.append('name', this.state.name);
Data.append('time', this.state.time);
Data.append('portion', this.state.portion);
Data.append('method', this.state.method);
Data.append('tags', JSON.stringify(this.state.tags));
Data.append('ingredients', JSON.stringify(this.state.ingredients))
Data.append('level', this.state.level)
console.log(Data)
axios.post('/api/post-recipe', Data)
.then(res => res.data)
.then(data =>{
console.log(data.dish)
})
.catch(err => {
if(err.response){
if(err.response.data.redirect === true){
window.location.replace(err.response.data.location)
}
if(err.response.data.message){
alert(err.response.data.message)
}
}
})
SERVER:
router.post('/', async (req, res) => {
try {
const {
name,
time,
portion,
ingredients,
method,
level,
tags
} = req.body
console.log(name + time + portion + ingredients + method + level + tags)
} catch (error) {
return res.status(500).send({
message: error.message
})
}
})
and it logs NaN in console and if i add words in console like 'name: ' name and etc. it logs undefined values, i have installed form-data from npm and i am importing it to my code and i can not get what is problem

You seem to be posting data to /api/post-recipe/ but looking for it on route /
You are logging to console the result of the mathematical sum of your variables - log them individually or read further on MDN

The route you send your data to (/api/post-recipe) does not match the route on the server (/) where you handle it. You either have to change the call to axios in the client, or you have to adjust the route definition on the server to match /api/post-recipe.
Additionally, you try to concatenate the individual strings with +, but this does not necessarily work. Try
console.log(name, time, ...);
instead and put in the other variables for .... If you also would like to know the variables' names, and not just their values, encapsulate all the parameters to console.log in a pair of curly braces:
console.log({ name, time, ... });
This turns the parameters into an object, and will also show their names.

Related

FormData sends undefined file to backend although the value has been assigned?

this might seem like a trivial question, but I'm truly don't know what is wrong with my code.
So, I've made this function that make a FormData, append it with name and value then sends it to the backend api:
const addGroup = () => {
const token = Cookies.get("X-API-KEY");
const formData = new FormData();
formData.append("firstlead", "Is Me");
formData.append("secondlead", "Is You");
formData.append("name", "Our Group");
axios
.post(
`http://localhost:7000/api/v1/groups`,formData,
{
headers: { authorization: token },
}
)
.then(() => {
notify();
});
};
The backend api code is:
// API POST DATA GROUP (admin)
router.post('/',authAdminMiddleware, async (req, res) => {
const {
firstlead,
secondlead,
name
} = req.body;
try {
console.log(firstlead)
console.log(secondlead)
console.log(name)
} catch (error) {
console.log(error);
return res.status(500).json({code:500,status:false,message:'Server Error'});
}
})
I don't know why, but the backend console log said that all of my variables (firstlead, secondlead, and name) are undefined despite it's clearly has been assigned a value. I've tried using Postman, and it actually works, so my guess is there is something wrong with my append code on the frontend, but again, I don't know what it is. Any help will be appreciated!
Below is the console.log from the backend, it receive undefined despite the value of firstlead, secondlead, and name has been declared on the addGroup function.
Undefined from backend

How to return value of both of the consecutive async functions in JS?

I've recently started with web development, and am a novice in JavaScript.
I'm currently working on a Blog Project and using Firebase as the backend, and Firestore as the Database.
PROJECT-
using the following project structure
Firestore DB ->
-Posts
-post1
-post2
-post3
...
-authors
-author1
-author2
..
-subscribers
...
I'm using this function to retrieve my posts from Firestore.
app.get('/:id', (req, res) => {
const id = req.params.id;
async function getDocument(id) {
const doc = await db.collection('Posts').doc(id).get();
if (!doc.exists) {
console.log('No such document!');
} else {
return doc.data();
}
}
getDocument(id).then(function (data) {
res.render('post',{ articleInfo:data} );
// that send back an object containing post details
})
Now, from the JSON I get from the above function, I want to use the value of "Author" to get the author's details from the another collection(run another async function),
and then send this data along with the data from previous function(used to get post details) together in res.render()
For example
I make a get request for a post and get back it's details. Inside which get the author's name "{..,"author : mike-ross",..} " .
Now, after .then, I use this value to run another async function get this author's JSON from the Authors collection. and pass the result from both the functions together in res.render() to get diplayed on the page.
You could have one async function that does both calls and returns an object with both results:
async function getDocWithDetails (id) {
const doc = await getDocument(id);
const authorInfo = await getAuthorInfo(doc.author);
return {
doc: doc.data(),
authorInfo: doc.data()
}
}
getDocWithDetails(id).then((data) => {
res.render('post', data) // has data.doc and data.authorInfo
});
Just go for it, same way you did the first half :-)
In general (at least at my work projects), it's good practice to setup multiple getters for each collection or one main getter where the collection is a secondary argument.
Here's the second variant with dynamic variant (but the first one is just as valid). Especially if you're not using typescript or flowtype to typecheck what you're passing, then it's more prone to unexpected errors by passing incorrect param, I'm just lazy to write the similar function in the answer twice.
const getDocumentById = async (id, collection) => {
const doc = await db.collection(collection).doc(id).get()
if (!doc.exists) {
throw Error(`Doc with id "${id}" doesn't exist on collection "${collection}"`)
}
return doc.data()
}
Now that we have our generic getter setup, you just need to create a function that fetches both.
As a precursor, I have taken some creative liberties with the answer, since the question is missing some cruicial info about documents.
At the very least (and if you don't you should, it's good firebase practice) I presume you have a link to the authorId inside Posts document.
Posts
-> post
-> id
-> authorId
-> some_other_fields
Authors
-> author
-> id
-> some_other_fields
With the following structure in mind, your answer will look something like this:
const getAuthorByPostId = async (id) => {
try {
const post = await getDocumentById(id, 'Posts')
const { authorId } = post
const author = await getDocumentById(authorId, 'Authors')
// I'm not sure how your res is structured, but could look something like this
res.render('page', { articleInfo: post, authorInfo: author })
} catch (error) {
console.error(error.message)
}
// in case it was unable to fetch data
return null
}

Post Multiple Objects Inside Express Route

I would like to post multiple objects to my mongo database inside of an express route. Currently, everything is working fine when I do it as a single object (ie ONE casino), please see below, but instead of doing this a million times over, can someone help me do it as one giant data dump so I can post ALL my casinos?
Here is my route that works fine for posting a single object:
router.post('/post', async (req, res) => {
console.log(req.body);
const casinoD = new Casino({
casino: req.body.casino,
table_and_other: req.body.table_and_other,
poker: req.body.poker,
slot_machines: req.body.slot_machines,
total_gaming_win: req.body.total_gaming_win,
year: req.body.year,
month: req.body.month,
combined_date: req.body.combined_date
})
try {
const newCasino = await casinoD.save()
res.status(201).json(newCasino)
} catch (err) {
res.status(400).json({ message: err.message})
}
})
I also understand mongoimport is a better way to do this - however that had its own issues in of itself.
Thanks
Like #JDunken said, you can iterate over the POST body as an array and insert in bulk. You'll want to use
insertMany for speed. To insert millions of records, you will probably want to put a sane limit on the number of records per request, and send API requests in batches. Validation is optional, as Mongoose will run validation according to the schema. It depends on how you want to handle validation errors. Make sure to read up on the ordered and rawResult options for that as well.
router.post('/post', async (req, res) => {
// you should sanity check that req.body is an array first, depending on how robust you want error handling to be
const casinos = req.body.filter(input => isValid(input));
try {
const insertedCasinos = await CasinoModel.insertMany(casinos, { ordered: false });
res.status(201).json(insertedCasinos)
} catch (err) {
res.status(400).json({ message: err.message})
}
})
const isValid(input) {
let valid = true;
// implement input validation
return valid;
}

Twilio SMS message keeps resending the same message

So I'm trying to send notifications to users phones with Twilio, however, the same message is sent three times. I do have three phone numbers hardcoded into an array (providerNumbers) so I think it's looping through three times because of this.
What I'm trying to do is eventually populate the phone numbers array from user-provided phone numbers they store on Firebase for each user. So a different user will receive the same notification to let them know to visit the website.
Here's my Node.js code:
var providerNumbers = ['number1', 'number2', 'number3'];
var body = "..."
app.get('/testtwilio', function(req, res){
Promise.all(
providerNumbers.map(number => {
return twilio.messages.create({
to: number,
from: '+15704058347',
body: body
});
})
).then(messages => {
console.log('Messages Sent!');
}).catch(err => console.error(err));
});
Anyone know how I can prevent the message sending three times to all the users?
There is nothing wrong with the code you posted.
.map calls the callback function once for each element in your providerNumbers array.
The callback function sends only one message when executed.
You can verify this if you log the index with something like this:
app.get('/testtwilio', function(req, res){
Promise.all(
providerNumbers.map((number, index) => {
console.log(index);
return twilio.messages.create({
to: number,
from: '+15704058347',
body: body
});
})
).then(messages => {
console.log('Messages Sent!');
}).catch(err => console.error(err));
});
In conclusion, something must be hitting your endpoint '/testtwilio' three times.
I hope this helps.
Your example seems to work, try checking the logs to see if multiple requests are being made to the same endpoint. A more concise method of mapping an array of primitives to promises would be using Promise.map. Reducing the usage of complex unit structures reduces the number of procedures your code has to perform, makes it easier to debug and to rule out false positives.
const providerNumbers = ['number1', 'number2', 'number3']
const from = '+15704058347'
const body = "..."
app.get('/testtwilio', (req, res, next) => {
Promise.map(
providerNumbers,
to => twilio.messages.create({to, from, body})
).then(res => {
console.log('Messages sent')
res.json({success: true})
}).catch(next)
})
I solved the problem by changing app.get to app.post.

Error: Registration token(s) provided to sendToDevice() must be a non-empty string or a non-empty array

I am trying to send the notification to devices within a circle of a radius of a point using firebase cloud functions. I am able to get the id of the devices within the circle but I am not able to get the token, the token is null as printed using console.log(token).
const getdevicetokenpromise = db.ref('/DriversAvailable/{key}/token').once('value');
console.log(key); //this value is right
return getdevicetokenpromise.then(result => {
console.log(result.val()); //this value is null, this is the problem
var token = result.val();
const payload = {
notification: {
title: 'title',
body: 'hey, well done dude',
icon: 'default'
}
};
return admin.messaging().sendToDevice(token, payload)
.then((response)=> {
return console.log("Successfully sent message:", response);
})
.catch((error) =>{
console.log("Error sending message:", error);
});
});
I have tried most of the things suggested on stackoverflow but coudln't find the solution. Thanks.
It looks like you're assuming that the value of key should be inserted into this string:
const getdevicetokenpromise = db.ref('/DriversAvailable/{key}/token').once('value');
That's not the way it's working, though. You are literally querying for that exact string, without key being inserted. I imagine you meant to use JavaScript syntax for variable interpolation using backticks around the string and ${} to delimit the variable:
const getdevicetokenpromise = db.ref(`/DriversAvailable/${key}/token`).once('value');

Categories