3

There is the following code:

 angular.module('app.services', []).factory('authService', [
'SIGN_IN_ENDPOINT', 'SIGN_OUT_ENDPOINT', '$http', '$cookieStore', function(SIGN_IN_ENDPOINT, SIGN_OUT_ENDPOINT, $http, $cookieStore) {
  var auth;
  auth = {};
  auth.signIn = function(credentials) {
    return $http.post(SIGN_IN_ENDPOINT, {
      user: credentials
    }).then(function(response, status) {
       return $cookieStore.put('user', response.data);
    }, function(error) {
       return console.log("Incorrect email/password");
    });
   };
  return auth;
} 

This is my module for authentication. Now I have the following function in controller:

angular.module('app.admin.controllers', []).controller('SignInController', [
  '$scope', 'authService', '$state', function($scope, authService, $state) {
    $scope.buttonText = "Login";
    return $scope.login = function() {
      $scope.buttonText = "Logging in. . .";
      return authService.signIn($scope.credentials).then(function(response, status) {
        return $state.go('allPosts');
      }, function(err) {
        $scope.invalidLogin = true;
        return $scope.buttonText = "Login";
      });
   };
} 

The problem: if I input wrong email/password, I'm waiting for 2 error callbacks - from the first 'then' from the second one, but I catch the first error callback (I can see console log) and after it THE SUCCESS callback executes! (return $state.go('allPosts')). Why? The Response from the server is 401 error.

2 Answers 2

3

The reason for this is, that you catch the error in the "app.services" and dont "bubble" the problem to higher tiers.

angular.module('app.services', []).factory('authService', [
'SIGN_IN_ENDPOINT', 'SIGN_OUT_ENDPOINT', '$http', '$cookieStore', function(SIGN_IN_ENDPOINT, SIGN_OUT_ENDPOINT, $http, $cookieStore) {
  var auth;
  auth = {};
  auth.signIn = function(credentials) {
    return $http.post(SIGN_IN_ENDPOINT, {
      user: credentials
    }).then(function(response, status) {
       return $cookieStore.put('user', response.data);
    }, function(error) {
       console.log("Incorrect email/password");
       return $q.reject();  //here is the important one.
    });
   };
  return auth;
} 

Or completely miss out the error handler.

auth.signIn = function(credentials) {
        return $http.post(SIGN_IN_ENDPOINT, {
          user: credentials
        }).then(function(response, status) {
           return $cookieStore.put('user', response.data);
        });
       };

If you catch the error and return a value within the error, following promises dont know about the occured error.

Sign up to request clarification or add additional context in comments.

3 Comments

Ok Thanks. But why I don't need to 'bubble' success to higher level? Should I do it only for errors? Thanks.
By returning a value within one of the callbacks in then, you basically bubble the success
TBH the official doc about $q should contain this information, but i didn't find it yet. I did discover it by myself (the hard way). docs.angularjs.org/api/ng/service/$q
2

Since the auth service is returning the promise returned by then function, in the first error callback you need to return rejected promise.

You can do it in this way:

auth.signIn = function(credentials) {
    return $http.post(SIGN_IN_ENDPOINT, {
      user: credentials
    }).then(function(response, status) {
       return $cookieStore.put('user', response.data);
    }, function(error) { 
       console.log("Incorrect email/password");
       return $q.reject(error);   // return a rejected promise;
    });
   };

Also remember to inject $q into your service, for this to work.

The promise returned by then is resolved with the return value of success and error callback functions. If you do a standard return, you will always land up on the success path. When you return $q.reject you are returning a promise that is eventually rejected. See documentation on $q.

You can also throw an exception from error callback in the service and get the same result.

1 Comment

why I don't need the same ($q.reject) for success callback? Does AngularJs do it automatically?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.