I am trying to setup Cloud Code in Parse for Mailgun to send emails. I have successfully done with writing the Java Script code mentioned below
Parse.Cloud.define("SendEmail", function(request, response) {
var Mailgun = require('mailgun');
Mailgun.initialize('myDomainName', 'MyKey');
Mailgun.sendEmail({
to: request.object.get("to") ,
from: "info#sample.com",
subject: request.object.get("subject"),
text: request.object.get("text")
},{
success: function() {
response.success(request.params);
console.log("--email sent - success");
console.log(request.params);
},
error: function() {
console.log("--failed to send email - success");
console.error(request.params);
response.error("Uh oh, something went wrong");
}
});
});
But I am continuously getting the following error
Error: TypeError: Cannot call method 'get' of undefined
at main.js:1:602 (Code: 141, Version: 1.2.20)
2014-08-20 02:05:03.725 PhotoAlert[475:60b] Error : Error Domain=Parse Code=141 "The operation couldn’t be completed. (Parse error 141.)" UserInfo=0x15ec5b90 {code=141, error=TypeError: Cannot call method 'get' of undefined
at main.js:1:602}
I am anxiously looking for solution as I am new for Parse/Mailgun and JS too.
Regards
I believe that where you have:
request.object.get("to")
It should be:
request.params.to
And that goes for all of the parameters that you are passing into the CloudCode Function (to, subject and text).
Being very new to this myself, Im guessing that the error is saying that the is no argument being passed in called "object" therefor there is no "get" method for it.
Related
I have the following AJAX that will send the entered data to the node server and the controller will check whether such data exist in the database or not.
If I do enter the data correctly, then everything is working fine.
However, I tried enter anything that the database does not have and it immediately throw an error, causing the server to stop. The error said that I did not handle the event, so I tried with res.json(err) in the controller instead of throw new Error, hoping that the error will be passed back to AJAX under the error key, but it is still not working. The error still gets thrown and the node server terminate itself.
I would like the server to continue and alert to the user that the data that was entered is not in the database but I have no idea why my approach is not correct.
I was thinking of using this SO thread if I'm able to get the error message back first from server side.
jQuery Ajax error handling, show custom exception messages
To solve the server from stopping, I used the code in app.js that was referred from this link
How do I prevent node.js from crashing? try-catch doesn't work
I'm not sure whether should I use the accepted answer for my case.
function createProduct(inputval){
let inputAction = window.location.pathname;
$.ajax({
type: "POST",
url: inputAction,
data: {order: inputval.split('-')[0].trim(), lot: inputval.split('-')[1].substring(0,5)},
success: function(data) {
$('#product').val('');
//Another function to add HTML
display(data);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log("XHR" + jqXHR)
console.log("Status" + textStatus)
console.log(errorThrown)
}
});
}
Controller File
exports.createProduct = function (req, res) {
db.Product.findOne({ "order": req.body.order, "lot": req.body.lot }).exec(function (err, product) {
if (!product || err){
throw new Error("The product entered returns null");
}
res.json(product);
});
};
Main File: app.js
process.on('uncaughtException', function (err) {
console.error(err);
console.log("Node NOT Exiting...");
});
You should use correct status code for your response. I suggest change your controller like below snippet
exports.createProduct = function (req, res) {
db.Product.findOne({ "order": req.body.order, "lot": req.body.lot }).exec(function (err, product) {
if (err){
res.status(500).end();//means internal server error
} else if (!product) {
res.status(404).end();//means product not found
} else {
res.json(product);
}
});
};
I finally figure it out thanks to feedback from other community, so I thought I would just share it here. It's so simple and silly me for neglecting such statement.
First, the code in app.js can just be removed.
Second, based on the answer given by #Milad Aghamohammadi. Instead of just:
res.status(500).end();
Use:
return res.status(500).json({err: "Server error"});
This way, the error is able to be handled by the AJAX error function and the node server will not be terminated from the event loop.
I am new to Node.js and i am trying to refresh the data periodically using the below code:
router.post('/getMessage',function(req,res){
setInterval(findMessage,5000);
function findMessage() {
Message.find(
{
$or: [
{sender: req.body.sender, receiver: req.body.receiver},
{sender: req.body.receiver, receiver: req.body.sender}
]
},
(err, data) => {
res.send({success: true, data: data});
}
);
}
});
But this gives an error: "Cannot set headers after they are sent". I understand that res.send calls res.end() implicitly and therefore this error is occuring. And have tried res.write() also. But i am returning an object and not a String or buffer, hence it also failed to work.
It would be great if someone could give an example of how to achieve this exactly.
response.send() method does two task
1. write content on the response and send.
2. End connection with res.end().
So, when you did response.send(), then it sends your message and closes the connection. For that reason, you getting the error "Cannot set headers after they are sent".
So, the conclusion is that you can't send multiple responses using response.send().
You can achieve this by the socket.io or you can make the request from frontend after an interval.
This problem annoys me, because I know it has something to do with me not understanding the issue properly - which makes it really hard to track down answers for, despite spending hours reading and trying different things.
My question/problem is this, I am saving a user to a mongodb database when they signup, my schema doesn't allow for duplicate emails, and sends me back an error. I am able to console log the error in the terminal, but I am having problems sending it back to the client. Or I'm having a problem doing something with it, if it comes back, I'm not too sure where in those two steps I am losing access to the error message.
Here is my POST route for saving the user:
router.post('/users', (req, res) => {
let body = _.pick(req.body, ['email', 'password']);
let user = new User(body);
user.save().then(() => { // this all works and will save the user, if there are no errors
return user.generateAuthToken();
}).then((token) => {
res.header('Authorization', `Bearer ${token}`).send(user);
}).catch((err) => { // This is where my problem is
console.log(err); // This will log the mongodb error here, about duplicate emails
res.status(500).send(err); // I'm trying to send the mongodb error message back to the client to display it on the screen (I will handle making the message friendly to read, once I can get this to work)
});
});
So my catch is getting the mongo error, and then I try to respond with it, by sending it to the client.
Here is my client side code:
axios({
method: 'post',
url: '/auth/users',
headers: {
'Content-Type': 'application/json'
},
data: {
email,
password
}
}).then((res) => {
console.log('this is the response', res);
if (res.status === 200) {
var authToken = res.headers.authorization.split(' ')[1];
authenticateUser(authToken);
this.props.history.replace('/dashboard');
} // This all works fine for a signup with no errors
}).catch((err) => {
console.log('Signup error:', err);
// I am expecting the above line of code to log the long Mongodb
// error message that I am sending back in my res.status(500).send(err)
// catch call from the server, but instead all I am getting is
// "Signup error: Error: Request failed with status code 500"
});
Either I'm not sending the error correctly, or I'm not handling it correctly when it comes back, but I have no idea which it is or why.
I can't even send back res.status(500).send('some string here') and access that string.
Thanks
Update
So I just checked in postman, by sending a POST that could cause the error, and I am getting the correct response sent through.
My server catch actually looks like this:
.catch((err) => {
res.status(500).send({message: err.message});
});
And the postman response body looks like this:
{
"message": "E11000 duplicate key error collection: authBoilerplate.users index: email_1 dup key: { : \"email#example.com\" }"
}
So I'm just not handling it correctly in my client side code, still at a loss though.
Thanks everyone, I was able to find the answer to my question, so I'm posting it here in the hope that it might help someone else.
I was definitely sending my custom error message back, I just wasn't handling it properly on the client side.
When I was using a catch call on the client and logging the error, I was expecting to see everything included in the error. It turns out that the error comes back with a response property error.response, and that is where all the messaging is.
So changing my catch call to this:
axios(//... send post in here)
.then(// ... same as in my question)
.catch((err) => {
console.log('error', err);
console.log('error response', err.response); // this is where the actual error response message is error.response.message
});
resulted in logging the stack trace and the error response:
error Error: Request failed with status code 500
at createError (eval at <anonymous> (bundle.js:541), <anonymous>:16:15)
at settle (eval at <anonymous> (bundle.js:847), <anonymous>:18:12)
at XMLHttpRequest.handleLoad (eval at <anonymous> (bundle.js:520), <anonymous>:77:7)
error response Object {data: Object, status: 500, statusText: "Internal Server Error", headers: Object, config: Object…}
I was still expecting to be able to see that I had access to that 'response' property by logging just the error, so if anyone has any insight into that, it would be great to include in the comments.
Another way of solving this is by converting the error to string.
.catch((err) => {
res.status(500).send(err.toString());
});
To preface this, I'm very new to Meteor and have never used Twilio before, so I'm probably just making a silly mistake somewhere.
I'm using the Twilio API bindings found here and trying to get a simple snippet of code working to send an SMS message within a Meteor.methods function. Here's the event trigger and method function:
if (Meteor.isClient) {
Template.twilioPlayground.events({
"click button": function() {
Meteor.call("sendSMS");
}
});
}
Meteor.methods({
sendSMS: function () {
twilio = Twilio('i put my account sid here', 'and my auth token here');
twilio.sendSms({
to:'+7199634882',
from: '+17194530451',
body: 'This is a test'
}, function(err, responseData) { //this function is executed when a response is received from Twilio
if (!err) {
console.log(responseData.from); // outputs "+14506667788"
console.log(responseData.body); // outputs "word to your mother."
}
});
}
});
So when that event is triggered, I'm getting the following error:
ReferenceError: Twilio is not defined
at Meteor.methods.sendSMS (http://localhost:3000/myTodoApp.js?8ae55884eab4c6a28ef9da8344fcf0b9d15c24ac:194:18)
at http://localhost:3000/packages/ddp.js?1f971b2ac9f4bdab7372cb5098ed1e26ff98dfb2:4239:25
at _.extend.withValue (http://localhost:3000/packages/meteor.js?61916b1060b33931a21f104fbffb67c2f3d493c5:945:17)
at _.extend.apply (http://localhost:3000/packages/ddp.js?1f971b2ac9f4bdab7372cb5098ed1e26ff98dfb2:4230:54)
at _.extend.call (http://localhost:3000/packages/ddp.js?1f971b2ac9f4bdab7372cb5098ed1e26ff98dfb2:4108:17)
at Object.Template.twilioPlayground.events.click button (http://localhost:3000/myTodoApp.js?8ae55884eab4c6a28ef9da8344fcf0b9d15c24ac:106:20)
at null.<anonymous> (http://localhost:3000/packages/blaze.js?77c0809654ee3a10dcd5a4f961fb1437e7957d33:3103:18)
at http://localhost:3000/packages/blaze.js?77c0809654ee3a10dcd5a4f961fb1437e7957d33:2371:30
at Object.Blaze._withCurrentView (http://localhost:3000/packages/blaze.js?77c0809654ee3a10dcd5a4f961fb1437e7957d33:2029:12)
at null.<anonymous> (http://localhost:3000/packages/blaze.js?77c0809654ee3a10dcd5a4f961fb1437e7957d33:2370:26)
Aside from adding the mrt:moment and mrt:twilio-meteor packages to the project, I didn't do any more setup. Any help is greatly appreciated.
You defined your method on both client and server. But the Twilio symbol is not even exposed on the client (because it is something client doesn't need to know about). Hence you get this error. Put your sendSMS method definition into Meteor.isServer block and it should work fine.
So, my Javascript isn't the best but I have to venture into it to run some Cloud Code functions. I have the following:
Parse.Cloud.define("setCommentIsTitle", function(request, response) {
Parse.Cloud.useMasterKey();
var query = new Parse.Query("Comment");
query.equalTo("objectId", request.params.objectId);
query.first({
success: function(object) {
object.set('isTitle', request.params.isTitle);
return object.save(); },
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
I logged the objectId I'm passing in as request.params.objectId and it's correct. What I don't get is that success is being called, but then I'm getting the following Cloud Code log when I console.log object:
I2013-10-21T17:27:52.120Z] object = undefined
And the following error returned in XCode:
code=141, error=TypeError: Cannot call method 'set' of undefined
If I'm calling the first function on query, and success is being called, shouldn't that mean there is an object returned? Why is object undefined?
OK, so this was a stupid error on my part, but also abetted by a confusing Parse error message.
My class is called Comments and not Comment, so I was looking up the wrong class. However, since success was called on the query I started looking in all the wrong places for the error.
Why would success be called if I'm querying a class that doesn't even exist??