Angular $q.reject().success(), does that make sense?
Asked Answered
P

1

6

I'm reading a book called MEAN Machine, and as I'm getting to the late chapters, I've got stuck at one of the sample applications, that doesn't seem to work.

The problem seems to occur because my mainController calls authService's Auth.getUser() method, which may return either a $http.get() or a $q.reject(). As I'm not logged in, it returns $q.reject(), and fails to chain the .success() promise.

It throws following exception:

TypeError: undefined is not a function at mainCtrl.js:13

My code is as follows.


CONTROLLER
mainController

angular.module('mainCtrl', [])
    .controller('mainController', function($rootScope, $location, Auth) {
        var vm = this;

        // check to see if a user is logged in on every request
        $rootScope.$on('$routeChangeStart', function () {
            vm.loggedIn = Auth.isLoggedIn();

            // get user information on route change
            Auth.getUser()

                /* ========= PROBLEM HERE ========= */
                .success(function (data) {
                    vm.user = data;
                });
        });

        // ... other stuff
    });

SERVICE
authService

angular.module('authService', [])

    // ===================================================
    // auth factory to login and get information
    // inject $http for communicating with the API
    // inject $q to return promise objects
    // inject AuthToken to manage tokens
    // ===================================================
    .factory('Auth', function ($http, $q, AuthToken) {

        var authFactory = {};

        // get the user info

        /* ========= PROBLEM LEADS HERE ========= */

        authFactory.getUser = function () {
            if (AuthToken.getToken())
                return $http.get('/api/me', { cache: true });
            else {
                return $q.reject({ message: 'User has no token.' });
            }
        }

What am I missing?

Pterous answered 14/3, 2015 at 14:21 Comment(2)
Have you defined an .isLoggedIn() method in Auth?Lyndialyndon
Hi @JLRishe. Yes, it's already defined. The problem really occurs when it tries to call .success() on return from $q.reject(). But thanks for your time.Pterous
V
8

Replace your call to the service with:

Solution A: .then(successCallback, errorCallback):

Auth.getUser().then(
    function (response) { ... },                // success handler
    function (response) {                       // error handler
        // case where user is not logged in
        // or http request fails
});

or

Solution B: .then(successCallback).catch(errorCallback):

Auth.getUser()
    .then(function (response) { ... })         // success handler
    .catch(function (response) {               // error handler
        // case where user is not logged in
        // or http request fails
    });

Explanation :

Your getUser method is defined as follows :

authFactory.getUser = function () {
    if (AuthToken.getToken())
        return $http.get('/api/me', { cache: true });
    else {
        return $q.reject({ message: 'User has no token.' });
    }
} 

But the success and the error shorthand methods are specific to $http. They doesn't exist in angular's promise $q API. Therefore, when the user is not logged in, because you are returning a $q promise, you got an undefined is not a function.

The methods you can call on a $q promise object are (link to documentation) :

  • then(successCallback, errorCallback, notifyCallback)
  • catch(errorCallback) which is a shorthand for promise.then(null, errorCallback)
  • finally(callback, notifyCallback)
Vickey answered 14/3, 2015 at 14:46 Comment(1)
Thank you very much, for both solution and explanation! It solved the problem.Pterous

© 2022 - 2024 — McMap. All rights reserved.