Do not execute following code if error callback - javascript

I am creating a REST api and I've defined this error handler:
function handleError(res, reason, message, code) {
console.log("ERROR: " + reason);
res.status(code || 500).json({"error": message});
}
But I think it needs some kind of interruption so that the following code is not executed, because if I implement my post method like this:
app.post("/contacts", function(req, res) {
var newContact = req.body;
newContact.createDate = new Date();
if (!(req.body.firstName || req.body.lastName)) {
handleError(res, "Invalid user input", "Must provide a first or last name.", 400);
}
db.collection(CONTACTS_COLLECTION).insertOne(newContact, function(err, doc) {
if (err) {
handleError(res, err.message, "Failed to create new contact.");
} else {
res.status(201).json(doc.ops[0]);
}
});
});
The server crashes and the invalid insertion is made into the database. I could solve this problem with an else for the insertion part, but I wanted to know if there is a way of not doing the rest of the method if the function handleError gets called.

Just return after call handleError function
//
if (!(req.body.firstName || req.body.lastName)) {
handleError(res, "Invalid user input", "Must provide a first or last name.", 400);
return;
}
//

A return statement will stop the rest of the function being executed.

Simply edit your handleError function so that the last line will be:
return res.status(code || 500).json({"error": message});
Or, in your /contacts handler :
if (!(req.body.firstName || req.body.lastName)) {
return handleError(res, "Invalid user input", "Must provide a first or last name.", 400);
}

Obvious answer is return or if somewhere higher up in the call stack you have error handling, throwing is also valid flow control, but depending on your use-case, there might be a cleaner method.
I'm guessing you are using express. Check this out.

Related

Channel.get not triggering

I'm using a RabbitMQ queue to publish and receive messages between consumers, the main issue is that I want to receive a single message then exit. From other answers on this site I've seen that channel.get seems to be the best way to do this. However, I can't get it to work. This is the answer I've been using.
My current code:
var amqpChannel = null;
var queue = "test";
amqp.connect(cluster, (error0, connection) => {
if (error0) throw error0;
connection.createChannel((error1, channel) => {
if (error1) throw error1;
amqpChannel = channel;
});
});
var readMessage = function() {
if (amqpChannel)
{
amqpChannel.get(queue, (err, msg) => {
if (err) console.log(err);
if (msg)
{
console.log("Message received: " + msg.content.toString());
amqpChannel.ack(msg);
}
});
}
}
setTimeout(readMessage, 1000);
As far as I can see, it is identical to the code in the accepted answer above, however I can't seem to get it to work. What am I missing?
Edit: Extra info
Using channel.consume works for me, it gets whatever messages are in the queue. However using the channel.get method results in nothing. I have used console.log lines to ensure the channel is being created properly, but for some reason the channel.get callback is never being triggered. I know that all the connection and queue creation is all working, I just can't seem to get the channel.get method to trigger at all.
Edit 2: I found the issue
My callback function wasn't correct. Looking at the documentation here, channel.get requires an options parameter before the callback, adding that in fixed my issue. My working code is now:
var amqpChannel = null;
var queue = "test";
amqp.connect(cluster, (error0, connection) => {
if (error0) throw error0;
connection.createChannel((error1, channel) => {
if (error1) throw error1;
amqpChannel = channel;
});
});
var readMessage = function() {
if (amqpChannel)
{
amqpChannel.get(queue, {noAck: true}, (err, msg) => {
if (err) console.log(err);
if (msg)
{
console.log("Message received: " + msg.content.toString());
amqpChannel.ack(msg);
}
});
}
}
setTimeout(readMessage, 1000);

SSJS Platform.Response.Redirect throws error in Try Catch Statement

I suspect threadabortexception issue of .NET but I couldn't fix it with possible options.
In short Redirect function throws an errors and goes to the catch, no matter to set the second parameter true or false).
The code below is just an example (but I faced this a couple of times before in real-time projects).
...
try {
var TSD = TriggeredSend.Init("DE_Name");
var Status = TSD.Send(data.subscriber, data.attributes);
if (Status != "OK") {
Platform.Response.Redirect(Variable.GetValue("#error_page"));
} else {
Platform.Response.Redirect(Variable.GetValue("#thanks_page")); //<<<-- This redirect throw error
}
} catch (err) {
Platform.Response.Redirect(Variable.GetValue("#error_page")); // <---- here it comes
}
...
Resources might helps:
1# https://support.microsoft.com/en-us/help/312629/prb-threadabortexception-occurs-if-you-use-response-end-response-redir
2# https://developer.salesforce.com/docs/atlas.en-us.mc-programmatic-content.meta/mc-programmatic-content/ssjs_platformClientBrowserRedirect.htm?search_text=Redirect
Any workaround is welcome.
I know this is an older question but I think it would be good to share findings.
There is no logical explanation to me why this is happen but the Redirect always throws an error and if it is used in a try block, the catch part will be executed.
Here is a simple workaround:
...
try {
var TSD = TriggeredSend.Init("DE_Name");
var Status = TSD.Send(data.subscriber, data.attributes);
try {
if (Status != "OK") {
Platform.Response.Redirect(Variable.GetValue("#error_page"));
} else {
Platform.Response.Redirect(Variable.GetValue("#thanks_page")); //<<<-- This redirect throw error
}
} catch(e) {}
} catch (err) {
Platform.Response.Redirect(Variable.GetValue("#error_page")); // <---- here it comes
}
...

Error handle in Meteor in calling server side method

I call a method for deleting family from server/publicationMehods like this:
deletedFamily(family) {
if (Meteor.user().roles[0] == "admin") {
var myUsers = Meteor.users.find({"profile.family_id": family._id}).fetch();
for (var i = 0; i < myUsers.length; i++) {
UsersDeleted.insert(myUsers[i]);
Meteor.users.remove(myUsers[i]);
}
var myGuests= Guests.find({"profile.family_id": family._id}).fetch();
for (var i = 0; i < myGuests.length; i++) {
GuestsDeleted.insert(myGuests[i]);
Guests.remove(myGuests[i]);
}
FamiliesDeleted.insert(family);
Families.remove(family);
}
}
I want to handle exception and catch it if any errors happend and in frond-end show the result. I know there is not any transaction in Meteor. But I need to show the result to user at least.
In Meteor, if you want to return an error to a user from a Meteor method then you throw an exception, but it must be a Meteor.Error exception object in order to send it back to the client.
On the client side, when you call a Meteor method on the server, you provide a callback function that receives an error and result. If you wish to display an error to the user then whatever Meteor.Error exception object that was thrown in the method will be in the error callback argument.
Here is an example. First let's look at the meteor method throwing an exception.
Meteor.methods({
deletedFamily: function(family) {
//... your logic here...
if (somethingWentWrong) {
throw new Meteor.Error("logged-out", "The user must be logged in to delete a family.");
} else {
return // something
}
},
});
On the client, you would call the method like this and if an error was thrown it will be in the error object.
// on the client
Meteor.call("deletedFamily", function (error, result) {
// identify the error
if (error && error.error === "logged-out") {
// show a nice error message
Session.set("errorMessage", "Please log in to delete a family.");
}
//...continue on with your logic...
});
If you need to pass along an exception generated by something else (mongodb for example), then just use try/catch blocks and pass a Meteor.Error when needed. Here is an example.
Meteor.methods({
deletedFamily: function(family) {
//... your logic here...
try {
// Mongodb insert or update
} catch(e) {
if (e instanceof WriteError && e.code === '11000') {
throw new Meteor.Error("duplicate-error", "The family already exists.");
}
}
},
});
You can use throw/catch.
Read the following document:
Throw

How to dictate a unit test response from a function in JS

I have a function here I'm writing a test for that calls another function on an external server (parse.com). Its my first time doing this type of thing.
How do I write a test so that second function function returns a specific value?
$scope.signInClick = function() {
console.log('Login was clicked');
console.log('$scope.user.username: ' + $scope.user.username);
console.log('$scope.user.password: ' + $scope.user.password);
$scope.loading = $ionicLoading.show({
content: 'Logging in',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
Parse.User.logIn(($scope.user.username) , $scope.user.password, {
success: function(_user) {
console.log('Login Success');
console.log('user = ' + _user.attributes.username);
console.log('email = ' + _user.attributes.email);
$ionicLoading.hide();
$rootScope.user = _user;
$rootScope.isLoggedIn = true;
$state.go('tab.home');
},
error: function(user, err) {
$ionicLoading.hide();
// The login failed. Check error to see why.
if (err.code === 101) {2
$scope.error.message = 'Invalid login credentials';
} else {
$scope.error.message = 'An unexpected error has ' +
'occurred, please try again.';
}
console.log('error message on Parse.User.logIn: ' + $scope.error.message);
$scope.$apply();
}
});
$state.go('tab.home');
};
I have to dictate that Parse.User.logIn returns an error, or a success, or an error of a particular type, so forth..
How do I mock that?
EDIT:
So, still been working on this, and I figured out one way to 'do' it, which was create a spy object just for the Parse.User.logIn (which is really the only thing being called).
But out of curiosity, why doesn't it work when I do that, but call $scope.signInClick ? Is there a way to get that function to call my spied on Parse object? When I try to call $scope.signInClick, I get that Parse is undefined.
Another thing: Is doing it this way missing the point of testing? Is this just dictating some code to do something, when we should be paying attention to the code that's actually in the app instead?
You can use dependency injection or monkey patching to replace the real Parse functions with your own.
var Parse = {
Unit: {
logIn: function(userName, pass, callbackObj) {
callbacObj.success({
attributes: {
username: "testuser",
email: "testuser#example.com"
}
});
}
}
};
The above is an example of the positive case but you could change it around to always call the error function instead.
There is no indication as to where Parse comes into the piece of code you've provided but basically what you should do is create a simplified mocked object that will act as the service, providing you with the results you'd normally expect from the real server.

Having trouble trying to execute find with MongoDB in node.js asynchronously

I'm grabbing a request parameter from my route e.g. mydomain.com/topic/animals where requestParam = req.params.topicName and in this case, animals.
I loop through an object containing all possible topics, and then if I find a topicName that matches the requestParam, then I want to execute a call to the database to return all collections for that topic.
The problem is it's being executed synchronously because it'll always execute the else clause e.g.
if (requestParam === topicName) {
// fetch submission
} else {
// return 404
}
So it's always returning the 404, but if I get rid of the else clause here, then it works. I looked into underscore's _.after() but couldn't get it to work properly (and not even sure if that's what I should be using?
My code:
_.each(topics, function(key, topic) {
var topicName = key['topicName'],
if (requestParam === topicName) {
Submission.getTopicSubmissions({ topicName : topicName }, function(err, submissions) {
if (err) {
res.redirect('/');
} else if (submissions) {
res.render('topic', {
submissions: submissions
});
} else {
res.redirect('/topics');
}
});
} else {
res.render('errors/404', {
title: 'Page Not Found -',
status: 404,
url: req.url
});
}
});
The problem is that you should not render 404 inside the each iteration. Because you do an asynchronous lookup, it is scheduled to execute at some point in the future while the current function keeps going. Undoubtedly you're going to run into a different one at some point and render 404 at least once. Use a breakable iteration, mark when you search, and do 404 outside of the iteration, like so:
var isWaitingForResult = false;
topics.every(function(topic, key) { // TODO: Check if this iterator matches _.each
var topicName = key['topicName'],
if (requestParam === topicName) {
isWaitingForResult = true; // Wait for the result.
Submission.getTopicSubmissions({ topicName : topicName }, function(err, submissions) {
if (err) {
res.redirect('/');
} else if (submissions) {
res.render('topic', {
submissions: submissions
});
} else {
res.redirect('/topics');
}
});
return false; // stop iteration, we did start our search after all
}
return true; // continue iteration so we have another chance.
});
if (!isWaitingForResult) { // did a search NOT start?
res.render('errors/404', {
title: 'Page Not Found -',
status: 404,
url: req.url
});
}
Note that I am unsure whether I re-wrote each to every correctly. Check this. :)

Categories