1

I am trying to continue my understanding of promises by writing a login function. The Login function is part of an AuthService that sends an http request to my server and returns a promise (the promise is resolved if the user is verified and rejected if not).

When calling the function in my controller I try to use .success and .error since the function returns a promise but I get the error "Undefined is not a function".

Here is my function that gets the undefined error.

$scope.login = function(email, password) {
  return AuthService.login(email, password).success(function(data) {
    return console.log("login function returned", data);
  }).error((function(data) {
    return console.log("There was an error " + data);
  }));
};

Here is my Service

.service('AuthService', function($window, $rootScope, $q, $http) {
  return {
    login: function(email, password) {
      var deferred;
      deferred = $q.defer();
      $http.post('/dashboard/login', {
        email: email,
        password: password
      }).error(function(error, status) {
        console.log("Incorrect logi");
        return deferred.reject(error);
      }).success(function(data, status) {
        $window.sessionStorage["userInfo"] = JSON.stringify(data);
        return deferred.resolve(data);
      });
      return deferred.promise;
    }
  };
});

What confuses me most is that after researching it seems like promises don't have a success or error method but $http is a promise that has that method. Also if they don't have success and error how do you know if something is an error or not? Lastly what is the point of .reject and .resolve if there is no success or error method?

Cœur
  • 37,241
  • 25
  • 195
  • 267
grasshopper
  • 918
  • 4
  • 13
  • 29
  • i think you want ".then()"... they almost made a ".done()", but got cold feet, so we just have _then_ – dandavis Oct 23 '14 at 04:03

1 Answers1

4

What confuses me most is that after researching it seems like promises don't have a success or error method but $http is a promise that has that method

Yes, indeed. $http return objects are promises that also have these .success and .error methods for legacy reasons.

if they don't have success and error how do you know if something is an error or not?

The standard way to attach handlers to a promise is using the .then() method, which also acts as a chaining method and returns a new promise for the results of the handlers.

So the code would look like this (also avoiding the deferred antipattern):

.service('AuthService', function($window, $rootScope, $q, $http) {
  return {
    login: function(email, password) {
      return $http.post('/dashboard/login', {
        email: email,
        password: password
      }).then(function(data, status) {
        $window.sessionStorage["userInfo"] = JSON.stringify(data);
        return data;
      }, function(error, status) {
        console.log("Incorrect login");
        throw error;
      });
    }
  };
});

$scope.login = function(email, password) {
  return AuthService.login(email, password).then(function(data) {
    return console.log("login function returned", data);
  }, function(err) {
    return console.log("There was an error " + err);
  });
};
Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • then what is the whole point of reject and resolve? also what do you mean by "attach handlers to a promise"? Do you have an example? – grasshopper Oct 23 '14 at 04:08
  • "attaching handlers" is just what `successs`/`error` do - so you "know if something is an error or not". – Bergi Oct 23 '14 at 04:12
  • 1
    The point of reject and resolve is the *notification* about the result, that the state has now settled. They do *trigger* this, and lead to the invocation of the callbacks (which were installed via `then`). Usually, when an API already returns a promise (such as `$http`), you don't have to deal with these deferreds at all - they're too low-level. You just do chaining and composing of promises. – Bergi Oct 23 '14 at 04:14
  • so basically reject and resolve are useless... I'll have to do some reading on throw. Wait how does the function know that err is an error? – grasshopper Oct 23 '14 at 04:15
  • 1
    No, you need them when you *create* a promise (from nothing, out of thin air, with nothing but an async callback). Also `then` uses them internally. Maybe starting reading at [this thread](http://stackoverflow.com/q/6801283/1048572) – Bergi Oct 23 '14 at 04:17
  • Sorry the useless part I wrote that before reading your second comment. I do not understand how the current function you wrote knows when there is an error? – grasshopper Oct 23 '14 at 04:22
  • The second argument to `.then`, the second callback, is called when the promise is rejected - when an error happens. How does the promise get rejected? I don't know, `$http` is responsible for that. Also, promises that are generated with the `.then()` method are rejected when a handler throws. – Bergi Oct 23 '14 at 04:25
  • @grasshopper for example - `$http` rejects when it cannot make the HTTP request, or when passed bad parameters. – Benjamin Gruenbaum Oct 23 '14 at 08:30