Meteor.js: Error not caught on client in method call - javascript

I am trying to throw a user defined error while updating a documents in mongoDb, if any error occures in Method. I am calling method and trying to catch the error, but i am not getting one. Error is printed only in server console. how can i catch the error in client side?
My code sample seems like this:
//Method
methodName: (userData) ->
if(Meteor.isServer and this.userId)
User.update {_id:this.userId},{$set:{username:userData.username, "profile.name": userData.name ,"emails.$.address": userData.email}}, (error) ->
if error and error.code == 11000
throw new Meteor.Error 403, 'Email already in used'
//client Side
$meteor.call('methodName',result).then ((success) ->
console.log success // is undefined in both case, when updates and in case of error
if success
console.log 'data updated'
), (err) ->
console.log err // not entered in this region

Your code has a large amount of errors.
Meteor.methods({
methodName: function(userData){
// you have to create the $set hash programatically first
var setHash = {
"$set": {
"username": userData.username,
"profile.name": userData.name,
// what's going on here with the dollar sign you originally had?
"emails.0.address": userData.email
}
};
if( Meteor.isServer && this.userId() ){
// It's Users, not User
return Users.update( { _id: this.userId() }, setHash, function(error, numberOfAffectedDocuments){
if(error && error.code == "11000"){
// Error names have to be a string
throw new Meteor.error("403", "Email already in use.");
} else {
return "Success! The number of affected documents is " + numberOfAffectedDocuments;
});
};
}
});
// in your original code you never sent your Meteor Method any arguments when calling it
Meteor.call('methodName', userDataObject, function(error, result){
if(error){
console.log("there was an error: ", error);
} else {
console.log("method call was a success: ", result);
};
});
References:
http://docs.mongodb.org/manual/reference/operator/update/set/#set-elements-in-arrays
http://docs.meteor.com/#/full/meteor_user

Your code has a couple of misconceptions
1) A method is a synchronous call. This means if it returns or runs completely before an error is fired the error callback will not be called on the client.
This means you need to use synchronous code throughout. At the moment, you are using a callback.
You can use this approach instead:
Meteor.methods methodName: (userData) ->
if Meteor.isServer and #userId
return User.update({ _id: #userId }, $set:
username: userData.username
'profile.name': userData.name
'emails.$.address': userData.email)
This will throw an error that will be received on the client with reason "Internal Server Error". As a 'catch-all' error. The difference between your code is there is no callback.
You can catch your specific duplicate key error using the try..catch pattern using this syntax.
2) User.update {_id:this.userId} will always run. You are looking for a "duplicate key", 11000, error when you update the document. This isn't the best approach to doing this. You should directly check for the email beforehand.
3) A method should return a value. At the moment, you don't return anything. You can only use one for the result, a callback or checking the value given back by the method. At the moment, you do both, so the result of User.update is undefined. This is why you see undefined. This should work:
Meteor.methods methodName: (userData) ->
if Meteor.isServer and #userId
if(User.emails.address':userData.email})) throw new Meteor.Error(500, "Email already exists");
return User.update({ _id: #userId }, $set:
username: userData.username
'profile.name': userData.name
'emails.$.address': userData.email)
else return false
So here you would directly check for a user having used the email and throw the Error & update it if it's not used. There are no callbacks so it should return a value to Meteor.call on the client.

Related

In nodejs Rest api call, puppeteer page evaluate not returning the response and throws the error

In nodejs Rest api call, puppeteer page evaluate not returning the response and throws the error.
How to return object after executing all the steps, without async
app.get("/api/register", function (req, res) {
res = page.evaluate((res) => {
webex.meetings
.register()
.then(() => {
console.log("Authentication#register() :: successfully registered");
return res.status(200).json({ message: "Successfully Registered" });
})
.catch((error) => {
console.error( "Authentication#register() :: error registering", error);
return res.status(400).json({ message: "Successfully Registered" });
})
}, res);
});
error
:\Users\sansubbu\git\webRTC\node_modules\puppeteer-core\lib\cjs\puppeteer\common\Connection.js:115
const stringifiedMessage = JSON.stringify(Object.assign({}, message, { id }));
^
TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Socket'
| property 'parser' -> object with constructor 'HTTPParser'
--- property 'socket' closes the circle Recursive objects are not allowed.
at JSON.stringify ()
at Connection._rawSend (C:\Users\sansubbu\git\webRTC\node_modules\puppeteer-core\lib\cjs\puppeteer\common\Connection.js:115:41)
at CDPSessionImpl.send (C:\Users\sansubbu\git\webRTC\node_modules\puppeteer-core\lib\cjs\puppeteer\common\Connection.js:320:82)
at ExecutionContext._ExecutionContext_evaluate (C:\Users\sansubbu\git\webRTC\node_modules\puppeteer-core\lib\cjs\puppeteer\common\ExecutionContext.js:211:46)
res is a complex, circular structure that only works in the Node environment. Even if you could, passing it to the browser console via page.evaluate() would take it out of Node, where it belongs, leaving it in an environment where it doesn't make any sense (browsers can't respond to requests as if they were a server).
Instead, try returning a boolean and branching on that on the Node side, where req/res are in their natural environment:
app.get("/api/register", async (req, res) => {
const success = await page.evaluate(async () => {
try {
await webex.meetings.register();
return true;
}
catch (err) {
return false;
}
});
if (success) {
console.log("Authentication#register() :: successfully registered");
return res.status(200).json({message: "Successfully Registered"});
}
console.error("Authentication#register() :: error registering", error);
// probably not the message you want but left as-is...
return res.status(400).json({message: "Successfully Registered"});
});
This is untested since you haven't provided a complete, reproducible example.
page.exposeFunction is another possible tool for triggering Node code based on a condition in the browser, but that seems like overkill here.
Finally, I'm not sure what page is, but typically you need a different page for each request. See this answer for suggested Express + Puppeteer boilerplate.

MongoDB query with promise not executing if statement (MongoDB node.js driver)

I'm trying to get my head around why the if(!document) is not executed when a document is not found, but instead the app jumps straight to the catch block and returns the 500 status instead?
To clarify, there's no problem with the id sent via req.body.id, if I send a valid ID that matches a doc in the db the success block is executed. The problem is when I send an ID that doesn't match a doc the if (!document) {} block is not executed, but instead the catch block is executed.
My intention is this (if the code example is not clear enough):
if the document is not found return:
return res.status(401).json({ message: 'Unauthorized.' }
If the document is found:
return res.status(200).json({ message: 'Authorized.' });
If there's a db / server error:
return res.status(500).json({ message: 'Internal server error.' })
Small code example below:
const login = (req, res) => {
userSchema
.findById(req.body.id)
.then((document) => {
if (!document) {
return res.status(401).json({ message: 'Unauthorized.' }).end();
}
return res.status(200).json({ message: 'Authorized.' });
})
.catch((err => return res.status(500).json({ message: 'Internal server error.' });
};
In order to successfully execute this part:
userSchema
.findById(req.body.id)
...
req.body.id has to be a value castable to an ObjectId. Otherwise you will see this error CastError: Cast to ObjectId failed for value..., which, of course, will trigger the catch block.
So, for example, if req.body.id is 604156ee6db28527531bd612, which is perfectly castable to ObjectId, your query will actually execute and, if no results are found, will trigger your if block.
If, however, req.body.id is, say, sh21343dfs or an empty string, then findById will throw the CastError mentioned above and send you straing into the catch block.
So just use the catch as your cue to send back something like a User Not Found error, because there are very few other things can trigger that catch block in findById
Or you could expicitly check for the validity of the string like so:
const ObjectID = require('mongodb').ObjectID;
...
...
if(ObjectID.isValid(req.body.id))
return res.status(401).json({ message: 'Unauthorized.' }).end();

Axios error status code UnhandledPromiseRejectionWarning

Using axios, I'm making GET requests to multiple links to test to see if they are broken links. If the GET requests returns an error, I want to log this error to the console and send it to the client side with socket. However, on some links (not all), I get an UnhandledPromiseRejectionWarning.
// check if the link is dead
axios.get(linkHref, {
auth: {
username: USERNAME,
password: PASSWORD
}
})
.then( (response) => {
if (response.status != 200) {
resultData = {
text: linkText,
url: linkHref,
statusCode: String(response.status)
}
console.log(resultData);
io.sockets.emit("result", resultData); // send link to client-side
}
})
.catch( (error) => {
if (error) {
resultData = {
text: linkText,
url: linkHref,
statusCode: String(error.response.status) // this is where the error is
}
console.log(resultData);
io.sockets.emit("result", resultData); // send link to client-side
}
});
I expect it work correctly and return the status code of the error but sometimes I get a UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'status' of undefined error. But with my if statement in the .catch, I am checking to make sure that there is an error and that it is not undefined so I don't understand why I'm getting this error.
EDIT: Also, this works (does not show me that error) when I run it on my Mac but not in Windows ... why?
TypeError: Cannot read property 'status' of undefined The response property on error.response is not defined eg error = { response: undefined }. Therefore, referencing any properties on it throws an error. error.response[property]
Also on failed/hanging http requests the error argument is different. Checkout this gist axios-catch-error. The error argument will have different properties for this case.
hey can you check by validating whether you are getting the response property on the error object in the if else condition
.catch( (error) => {
if (error.response) {
//rest of the code...
}
});

{Status: 202} when running a lambda from code

This is my code in Javascript:
var params = {
FunctionName: "theTable",
InvokeArgs: JSON.stringify({ "name": "KirklandWA" })
};
lambda.invokeAsync(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else {
console.log(data);
}
});
This is in Lambda:
exports.handler = async (event, context) => {
return "theReturnedValue";
};
What is happening is that it is not returning the theReturnedValue, instead returns
{Status: 202}
Status: 202
The code in Lambda is getting invoked, I made sure of it at Cloudwatch.
You're invoking with invokeAsync which will only return status code as stated in the documentation. Use invoke with InvocationType: "RequestResponse" instead
Reference:
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Lambda.html#invoke-property
var lambda = new AWS.Lambda({});
var params = {
FunctionName: "function_name",
InvocationType: "RequestResponse"
};
response = lambda.invoke(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
Verify that your lambda this selected as NodeJs 8.10 runtime, once having verified you must return a promise directly:
exports.handler = async (event, context) => {
return await new Promise((resolve, reject) => {
resolve({ message: "hello world" });
});
};
I was looking invokeAsync method definition in the aws-sdk documentation and the status code is fine:
Callback parameters:
err (Error) — the error object returned from the request. Set to null if the request is successful.
data (Object) — the de-serialized data returned from the request. Set to null if a request error occurs. The data object has the
following properties:
Status — (Integer) It will be 202 upon success.
I prepare you a basic example, please review handler.js file:
https://github.com/ns4lin4s/stackoverflow
Dont forget, that you must specify response body:
So when you finish, let me know how that works!
The problem is that your lambda function is not returning anything back to the caller.
Your handle funtion has a third parameter which is a callback function that is used to return results to the caller.
The callback function takes in two values, an Error and results
callback(Error error, Object result);
If you provide the Error values the lambda will throw the an error you provide to the user, if you dont provide an Error value but the results, its the results that will be returned
Its all documented very well here
Here are basic examples
callback(); // Indicates success but no information returned to the caller.
callback(null); // Indicates success but no information returned to the caller.
callback(null, "success"); // Indicates success with information returned to the caller.
callback(error); // Indicates error with error information returned to the caller.
Your handler function should be.
exports.handler = async (event, context,callback) => {
callback(null, "theReturnedValue");
};

TypeError: Cannot read property 'subject' of null

I am retrieving data of Template collection from mongodb. so my problem is when i give a wrong templateName the program is supposed to catch a error. But it doesn't do so. program goes further & i get error TypeError: Cannot read property 'subject' of null.
How to handle this thing?
Template.findOne({ name: templateName }, function (err, template) {
if (err) {
console.log('Error occured');
console.log(err.message);
callback(err);
}
else {
template_subject = template.subject;
template_html = template.dataMsg;
});
If wrong templateName is given, i want to return error to callback function.
Mongodb-native (the client library you're using) won't raise an error if your find did not return any document.
Errors are reserved for connectivity or syntax problems.
Therefore you must test the variable existence before using it, something like:
Template.findOne({ name: templateName }, function (err, template) {
if (err === null && template == null) {
// no error, but no result found
err = new Error(templateName + ' not found');
}
if (err) {
console.log('Error occured');
console.log(err.message);
// early return to avoid another indentation :)
return callback(err);
}
template_subject = template.subject;
template_html = template.dataMsg;
You can check before line no:8.
As subject is showing null.
if(template.subject && template.dataMsg){
// ok
} else {
// wrong templateName
}

Categories