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.
Related
I am desperate for some help with an issue I am having updating an item in a mongoDB database. I am creating a simple note application using nodeJS and I have set it up to add notes and remove notes to and from the database with no issues.
When I try to edit notes however, the update does not persist to the database. I dont get an error back and when I console.log the result it displays the correct data but just wont seem to push it to the data base. I have been using mongoose and findByIdAndUpdate. Here is the JavaScript code for my update route
app.put("/:id", (req, res) => {
Note.findByIdAndUpdate(req.params.id, req.body.note, (err, updatedNote) => {
if(err) {
console.log(err);
} else {
res.redirect(`/${req.params.id}`);
console.log(req.params.id);
console.log(req.body.note);
console.log("note updated");
}
});
});
As I mentioned, I dont get any error and the console.logs return the correct id and updated content. All my routes take me to the place so I don't believe there is an issue with them. Any help would be greatly appreciated. I can also provide more code if needed
Thanks in advance
Will
When updating in MongoDB, you have to reference the field you are trying to update. Your code should look like this
app.put("/:id", (req, res) => {
Note.findByIdAndUpdate(req.params.id, {text: req.body.note}, (err, updatedNote) => {
if(err) {
console.log(err);
} else {
res.redirect(`/${req.params.id}`);
console.log(req.params.id);
console.log(req.body.note);
console.log("note updated");
}
});
});
PS: I am hoping the field in the DB model is called text
To make the code look sexier, you can switch it to Async/Await
app.put("/:id", async (req, res) => {
let updatedNote = await Note.findByIdAndUpdate(req.params.id, {text:
req.body.note}, {new: true}).catch(err => console.log(err))
res.redirect(`/${req.params.id}`);
console.log(req.params.id);
console.log(req.body.note);
console.log("note updated");
});
That updatedNote is the same as before the update is expected behavior – see the mongooe docs:
By default, findOneAndUpdate() returns the document as it was before
update was applied. If you set new: true, findOneAndUpdate() will
instead give you the object after update was applied.
This does not mean the update did not take place.
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;
}
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.
I know this will be a simple answer but I've never had to do more than a single query at a time before!
I have a game item, and I want to return the games a user is part of as a list, it queries first to see if they're host, and then if they're a player. Then taking the result of both of those queries and sorting by createdOn time.
As you'll see, I have it working for the first query for gamePlayers.user, but I need to also be able to query host.user.
Like I said, I know this will have a simple answer but my googling is coming up empty and I'd appreciate any responses!
router.get('/currentgames', passport.authenticate('jwt', { session: false }),
(req, res) => {
const errors = {};
const userId = req.user.id;
Game.find({"gamePlayers.user": userId})
.limit(10)
.sort({lastUpdated: -1})
.then(games => {
if(!games) {
errors.nousergames = 'You have no games yet';
return res.status(204).json(errors);
}
res.json(games);
})
.catch(err =>
res.status(404).json({ game: 'There are no games'})
);
});
I've got a trouble when trying to implement backend firebase Authorization.
After I had read carefully the docs (https://firebase.google.com/docs/auth/web/phone-auth), I figured out that Authorization need to be proceded by two steps:
send phone
send code
I divided Google's example on two promises, but can't understand how to store current user and whether or not I've done everything in an appropriate way.
app.post("/appSignInByPhone", (req, res) => {
let {phoneNumber, applicationVerifier} = req.body;
firebase.auth().signInWithPhoneNumber(phoneNumber, applicationVerifier)
.then(() => res.end("Waiting for code"))
.catch(
error => res.json(error)
);
});
app.post("/appSignInPhoneVerify", (req, res) => {
let {verificationCode} = req.body;
firebase.auth.ConfirmationResult.confirm(verificationCode)
.then( user => res.json(user))
.catch(
error => res.json(error)
);
});
Maybe there are some ways of merging these to request to one...
Try the following:
In step #1 either store or send back the confirmationResult you get from the fulfillment handler:
firebase.auth().signInWithPhoneNumber(phoneNumber, applicationVerifier)
.then((confirmationResult) => {
// either store confirmationResult
// or send it to the client and ask for it in step #2)
}).catch(
error => res.json(error)
);
then in step #2:
// get the confirmationResult from the client or from some storage
// in the server
// for example let { verificationCode, confirmationResult } = req.body;
confirmationResult.confirm(verificationCode)
.then( user => res.json(user))
.catch(
error => res.json(error)
);