Peter Boomsma Peter Boomsma - 3 months ago 9
Node.js Question

Return error to Angular from Express

I have a application where users can add movies to their watchlist. I want to prevent users from adding a movie that already exists in their watchlist.

This my addMovie function in my Angular controller:

$scope.addMovie = function (movie) {
movieFactory.selectMovie(movie).then(function(response){
movieFactory.addMovie(response);
Notification.success(movie.title + ' has been added to your watchlist');
$scope.movies = [];
$scope.overlay = false;
$scope.searchquery = '';
$rootScope.$broadcast('onAddMovieEvent', response);
});
};


I pass the movie object through from my initial ng-click. Then I request a
selectMvoie
function in the
movieFactory
that gets the correct movie data from the TMDB api.

Then I call the
addMovie
function in the
movieFactory
factory with the response from
selectMovie
function.

factory.addMovie = function (movie) {
var deferred = $q.defer();
$http({
method: 'POST',
url: '/movies',
data: movie
})
.success(function (data) {
deferred.resolve(data);
})
.catch(function () {
deferred.reject();
});
return deferred.promise;
};


This does a
/post
request which goes into my Express route:

router.post('/', function(req,res){
pool.getConnection(function(err, connection) {

connection.query('SELECT * FROM user_movieid WHERE movie_id= ? AND userid= ?' ,[req.body.id, req.user.id] , function(err, result) {
for (var i = result.length - 1; i >= 0; i--) {

if (movie.id === result[i].movie_id) {
console.log('exists');
}
}
});
});
})


There's also a
connection.query
that posts the movie into the database but that's not relevant now.

My situation now is that when I post a movie that already exists my node console shows the message
exists
but still posts the movie (obviously).

How would I return an "error" status back to my
addMovie
function in my Angular controller so I can do a if statement to show a different notification?

Answer

If you want to keep your API 'restful' then I would return a response with a non 2xx status code. I would think 409 Conflict is appropriate for this case.

router.post('/', function(req,res){
    pool.getConnection(function(err, connection) {

        connection.query('SELECT * FROM user_movieid WHERE movie_id= ? AND userid= ?' ,[req.body.id, req.user.id] , function(err, result) {
            for (var i = result.length - 1; i >= 0; i--) {

                if (movie.id === result[i].movie_id) {
                    console.log('exists');
                    // choose an appropriate status code, probably a conflict 409 in this case
                    return res.status(409).send('Movie already exists in your watchlist')
                }
            }
        });
    });
})

Then in your Angular code you can notify the user that the movie is already in their list.

$scope.addMovie = function (movie)  {
    movieFactory.selectMovie(movie).then(function(response){
        movieFactory.addMovie(response);
        Notification.success(movie.title + ' has been added to your watchlist');
        $scope.movies = [];
        $scope.overlay = false;
        $scope.searchquery = '';
        $rootScope.$broadcast('onAddMovieEvent', response);
    })
    // catch any errors
    .catch(function() {
      // ideally you should check the status code here and probably handle other non 409 status codes differently
      // since this .catch will execute for any other 4xx and 5xx errors
      Notification.fail(movie.title + ' is already in your watchlist');
    });
};
Comments