0

I'm trying to pass the currently signed-in user to the resolve block of a 'user' state (I'm using ui-router), so upon sign-in, user will be in url of .../users/:id.

Other routes are nested inside :user route, so this seems the most logical path to me (I may be wrong).

I'm using angular_devise here so i should be able to extract the :id from from API via Auth, but I'm running into some trouble.

(Included other possible relevant files below.)

App.js

$stateProvder
  .state('users', { 
      url: '/users/{id}', 
      templateUrl: 'home/_home.html',
      controller: 'MainCtrl',
      resolve: {
          userPromise: ['$stateParams', 'users', 'Auth', function($stateParams, users, Auth) {
            return users.get(
                Auth.currentUser().then(function (user) {
                return user.id;
            })
          );
      }]
    }
  })

Users.js

.factory('users', ['$http', function($http) {
    var u = {
        userArray: []
    };
    u.get = function(id) {
        return $http.get('/users/' + id + '.json').then(function(res) {
            console.log('request: ', res.data);
            angular.copy(res.data, u.userArray);

        });
    };
    return u;
}]);

Users_controller.rb

class UsersController < ApplicationController
    def show
        @user = User.find(params[:id])
        authorize @user
        respond_with @user
    end
end

NavCtrl.js

.controller('NavCtrl', [
    '$scope',
    'Auth',
    function($scope, Auth) {
        $scope.signedIn = Auth.isAuthenticated;
        $scope.logout = Auth.logout;

        Auth.currentUser().then(function (user) {
            $scope.user = user;
        });

        $scope.$on('devise:new-registration', function (e, user) {
            $scope.user = user;
        });

        $scope.$on('devise:login', function (e, user) {
            $scope.user = user;
        });

        $scope.$on('devise:logout', function (e, user) {
            $scope.user = {};
        });
    }])
;

FYI. $http request is being sent to a rails backend.

I would be very grateful if anyone can advise what i might be doing wrong.

Pardeep Dhingra
  • 3,916
  • 7
  • 30
  • 56
tim_xyz
  • 11,573
  • 17
  • 52
  • 97

1 Answers1

1

I would be very grateful if anyone can advise what i might be doing wrong.

If we restate your code:

$stateProvder
  .state('users', { 
      url: '/users/{id}', 
      templateUrl: 'home/_home.html',
      controller: 'MainCtrl',
      resolve: {
          userPromise: ['$stateParams', 'users', 'Auth', function($stateParams, users, Auth) {
            var derivePromise = Auth.currentUser()
               .then(function (user) {
                    return user.id;
            });
            //WRONG - user.get does not accept promises
            return users.get(derivedPromise);
      }]
    }
  })

You can see that Auth.currentUser().then(fn) returns a derived promise and that the users.get function does not accept promises.


For future reference, how would i know this is actually a derived promise and not a number ?

Any object that has a .then method returns a derived promise. This is as specified by Promises/A+ open standard for interoperable JavaScript promises.

AngularJS uses the $q Service Promise API.

Chaining promises

Because calling the .then method of a promise returns a new derived promise, it is easily possible to create a chain of promises.

It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain. This makes it possible to implement powerful APIs.

Think of promises as a container for a value that will be returned in the future. That value can only be retrieved by registering functions (using the .then or .catch methods) with the $q service. The $q service holds those functions and invokes them when the promise is resolved either fulfilled or rejected. Those methods can also be used to retrieve results after the promise has resolved.

The $q service supports supports passing promises as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures.

In summary, returning a value to a .then method creates a new derived promise suitable for chaining. It will never return a value.

For more information, see Angular execution order with $q.

Community
  • 1
  • 1
georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • If i check `typeof()` for `console.log` output, it returns `number` for `Auth.currentUser().then(function (user) { console.log( typeof( user.id) );});`. For future reference, how would i know this is actually a `derived promise` and not a `number` ? – tim_xyz Mar 16 '16 at 01:20
  • Does that mean the only way to get a value out of a promise is to assign it to a variable like, `.then(function(user) { $scope.user_id = user.id })` ? – tim_xyz Mar 16 '16 at 02:18
  • 1
    The `$stateProvider` resolver accepts promises. Give it a derived promise chained from the `user.id` promise.. – georgeawg Mar 16 '16 at 02:33