5

I have a users service. I would like to create a method which utilizes another service I have built. There are two methods on this service. getUser() and getCurrentUser(). getCurrentUser() utilizes the injected service which acquires the UID. It uses the returned UID to run the getUser() method. My problem is that I can't get getCurrentUser() to return the second tier promise.

This question is a little bit difficult to explain. Here's the code...

svs.service("usersService", function($rootScope, $http, loginService, alertBoxService) {
  var self = this;
  self.getUser = function(identifier, column) {
    if (typeof(column) === 'undefined') column = "uid";
    return $http.get($rootScope.api + "/getUser/" + identifier + "/" + column);
  }
  self.getCurrentUser = function() {
    var currentUserPromise;
    loginService.getCurrentUid().then(
      function(response) {
        if (response.data === "false") {
          alertBoxService.trigger($rootScope.unexpectedApiResponse);
        } else {
          console.log(self.getUser(response.data));
          currentUserPromise = self.getUser(response.data);
        }
      }, function(response) {
        alertBoxService.trigger($rootScope.asyncFailed);
      }
    );
    return currentUserPromise;
  }
});
Allenph
  • 1,875
  • 27
  • 46
  • [Yes, of course](http://stackoverflow.com/q/23667086/1048572). But you don't need that variable at all! – Bergi Aug 31 '16 at 06:09

3 Answers3

4

Chain the promises but don't forget to chain the rejections too...

self.getCurrentUser = function() {
    return loginService.getCurrentUid().then(function(response) {
        if (response.data === 'false') {
            alertBoxService.trigger($rootScope.unexpectedApiResponse);
            return $q.reject(response); // convert into a rejection
        }
        return self.getUser(response.data); // chain the promise resolution
    }, function(response) {
        alertBoxService.trigger($rootScope.asyncFailed);
        return $q.reject(response); // chain the rejections
    });
}

You'll need to inject the $q service of course.


As Bergi kindly pointed out, you can also reject the promise by throwing an error instead of using $q.reject, eg

throw response;
Community
  • 1
  • 1
Phil
  • 157,677
  • 23
  • 242
  • 245
  • You might want to highlight the first added `return` as well, it's easily forgotten by those who learn about `then` – Bergi Aug 31 '16 at 06:10
  • What are we doing with `$q` here? – Allenph Aug 31 '16 at 06:10
  • 1
    Instead of using `$q.reject`, you can just re`throw` the error. – Bergi Aug 31 '16 at 06:11
  • @Bergi ah yes, I forgot about that. It wouldn't be *re-throwing* though as nothing has been *caught* ;) – Phil Aug 31 '16 at 06:11
  • 2
    @Allenph when a promise rejection is handled via the second argument to `then` or `catch`, it is converted into a resolved promise unless that handler returns a rejected promise or throws an error. This lets upstream consumers know that the promise was rejected. Otherwise, they will consider it successful. – Phil Aug 31 '16 at 06:15
  • 1
    @Allenph …and successful with `undefined` as the fulfillment value, which might be unexpected and cause further exceptions downstream. – Bergi Aug 31 '16 at 07:13
0

The problem here is that when the function getCurrentUser gets called, it immediately return an undefined variable. This is because the service is asynchronous and by the time the response is received on the service, the function call would have already returned an undefined variable. In order to prevent this you can add the return call inside the loginService.

Ananth Pai
  • 1,939
  • 14
  • 15
0

For a async function to return a promise from inside the success callback you have to return from the callback which is the promise object and then return from the main function in order to provide the promise to the caller.

Try this.

  svs.service("usersService", function($rootScope, $http, loginService, alertBoxService) {
  var self = this;
  self.getUser = function(identifier, column) {
    if (typeof(column) === 'undefined') column = "uid";
    return $http.get($rootScope.api + "/getUser/" + identifier + "/" + column);
  }
  self.getCurrentUser = function() {
    return loginService.getCurrentUid().then(
      function(response) {
        if (response.data === "false") {
          alertBoxService.trigger($rootScope.unexpectedApiResponse);
        } else {
          console.log(self.getUser(response.data));
          return self.getUser(response.data);
        }
      }, function(response) {
        alertBoxService.trigger($rootScope.asyncFailed);
      }
    );
  }
});