Javascript 如何在使用angular_Desive注销之前保持全局当前用户?

Javascript 如何在使用angular_Desive注销之前保持全局当前用户?,javascript,angularjs,devise,angular-ui-router,angular-services,Javascript,Angularjs,Devise,Angular Ui Router,Angular Services,如何创建自己的全局可访问的服务,该服务在页面加载时仅通过currentUser()调用服务器一次,如果用户已登录,则保留该服务并向控制器或状态提供数据,直到注销? 现在,我在许多州或控制器中多次解析currentUser(),我在文档中发现:有可能创建自己的服务,但我不知道如何以正确的方式处理此问题 e、 g在ui路由器中,我有两个服务器调用,只有在加载页面时才足够: .state('login', { url: '/login', templateUrl: 'auth/_login.h

如何创建自己的全局可访问的服务,该服务在页面加载时仅通过
currentUser()调用服务器一次,如果用户已登录,则保留该服务并向控制器或状态提供数据,直到注销?
现在,我在许多州或控制器中多次解析
currentUser()
,我在文档中发现:有可能创建自己的服务,但我不知道如何以正确的方式处理此问题

e、 g在ui路由器中,我有两个服务器调用,只有在加载页面时才足够:

.state('login', {
  url: '/login',
  templateUrl: 'auth/_login.html',
  controller: 'AuthCtrl',
  onEnter: [
    '$state', 'Auth',
    function($state, Auth) {
      Auth.currentUser().then(function() {
        $state.go('home');
      });
    }
  ]
})
.state('dashboard', {
  url: '/dashboard',
  templateUrl: 'dashboard.html',
  onEnter: [
    '$state', 'Auth',
    function($state, Auth) {
      Auth.currentUser().then(function(user) {}, function(err) {
        $state.go('home');// user not logged in
      });
    }
  ]
})
或者每次在NavController中调用下一个服务器时:

app.controller('NavController', [
  '$state', '$scope', 'Auth', function($state, $scope, Auth) {
    $scope.signedIn = Auth.isAuthenticated;
    $scope.logout = Auth.logout; // logout function
    Auth.currentUser().then(function(user) {
      $scope.user = user;
    });
    $scope.$on('devise:login', function(e, user) {
      $scope.user = user;
    });
    $scope.$on('devise:logout', function(e, user) {
      $scope.user = {};
      $state.go("home");
    });
  }
]);

我发现类似的问题没有答案:

我不得不在一个大型Angular应用程序中处理用户身份验证问题,并发现本文非常有用:

具体到“如何使其只发生一次”:

  • 您可以在app.run块中调用服务的init()
  • 将其添加为应用程序外部状态的
    解析
    要求(如果使用嵌套状态)
表示用户登录状态的
UserService
服务可以很好地在整个应用程序中共享状态。登录和注销功能可以通过该服务公开,用户的详细信息也可以存储在这里。定义扩展
$resource
UserApi
,也可能有助于将实际的HTTP关注点与管理用户状态分开


本文还讨论了其他一些问题:页面刷新的持久状态,以及只有用户登录时才能访问的站点区域。

我们知道,factory是一个单例对象,基本上用于数据共享。我们可以将它作为依赖项注入任何控制器和函数 .所以这也可能解决你的问题。将此服务注入状态解析块,检查用户是否存在,如果不存在,则调用工厂的fetch user函数

app.factory("User", function($http, $q, $rootScope) {
var user = null;
return {
    fetchUser: function() {
        /*your ajax call that return current user*/
        user = YOUR_SERVER_RESPONSE;
        return user;

    },
    getUser : function(){
        return user;
    },
    setUser : function(u){
        user = u;
    }
}
}))

您的状态配置块如下所示

  .state('dashboard', {
  url: '/dashboard',
  templateUrl: 'dashboard.html',
  resolve : function(User){
    if(User.getUser()){
        return User.getUser();
    }else{
        return User.fetchUser();
    }
  }
})

我通过在主HTML页面底部添加以下JavaScript(jQuery)代码,解决了angular当前用户信息的问题:

$("meta[name=current_user]").data('current_user', {
    id: <%=j current_user.id.to_s %>, 
    username: "<%=j current_user.full_name.to_s %>"
});
这是我的工厂代码,供用户使用(再次使用coffeescript):


如果您有任何问题,请告诉我。

将用户详细信息保存在全局中。用户使用控制器或服务中的“全局”模块


当您必须访问用户时,请使用全局访问。用户

编辑:更改某些部件,以便与angular\u设备模块一起使用

通常,我使用的是这里提供的解决方案(),它描述了如何检查每个HTTP调用的用户是否登录

如果用户已登录,则检查加载情况

我将创建一个名为“User”的附加服务(因为服务是单例的),定义一些方法,例如save()和get(),将用户保存到服务单例中,并在必要时返回它。
使用“checkLoggedIn”功能,您可以为您的路由定义一个“resolve”选项,如果承诺得到解决,则用户可以访问受限页面

您是否可以控制后端登录服务器?我将发布一个简单而常见的解决方案,但需要一个额外的服务器端功能。@FerTo我正在使用Ruby on Rails,所以我想将它与服务结合起来。哦,好吧,你应该“忽略”我的代码。好吧,我已经研究了angular_设备模块,看起来你可以使用我的“解决方案”将更改代码。我不想构建新服务,因此在这种情况下,这是与
angular\u DeVICE
合作的有趣概念,如果这种方法可以通过
ui路由器中的
User.fetchUser()
解决
Auth
服务的链接承诺,我将使用它。@luzny然后查看我的答案如果您只想检查它而不创建新服务,只需使用您的rootScope即可。我以前添加过完全相同的解决方案。正如您所描述的,您只需要检查“页面加载”,并将信息提供给其他每个服务/控制器。最简单的解决方案是使用rootScope,但我更喜欢使用基本用户Service@luzny是的,这种方法在连锁承诺中非常有效。我用这个概念是我的项目。“解析”每个块可能与要首先解析的前一个块有依赖关系,并且其工作正常。我在使用oclazyload和refresh应用程序时尝试过这一点。(当前状态为
N level
# Grab User Info
current_user = angular.element("meta[name=current_user]").data 'current_user'

# Stop Here if you Have the Info you Need
$scope.user = current_user

# **** OR Get More Info if User is Logged In 
if current_user.id is not undefined
   $scope.user = User.get {id: current_user.id}
# In order to prevent minification from effecting the code
# must wrap functions as arrays and pass in the variables as 
# strings before the function call
app.factory "User", ["$resource", ($resource) ->
    $resource("/api/angular/users/:id", 
    { id: "@id" }, 
    {
        update: { method: "PUT" }
    })
]
myApp.config(['$routeProvider','$locationProvider',
function($routeProvider, $locationProvider) {
//================================================
// Check if the user is connected
//================================================
var checkLoggedin = function($q, $rootScope, Auth, User){
  // Initialize a new promise
  var deferred = $q.defer();
  Auth.currentUser().then(function(userObj){
    deferred.resolve();
    //option a: just save the user object into the $rootScope
    $rootScope.User = userObj;
    //option b: create a factory 'User' and a method 'save()' which parses the JSON returned from your Server 
    User.save(userObj);
  }, function(error){
    deferred.reject();
  });
  return deferred.promise;
};


//================================================
// Define all the routes
//================================================
$routeProvider
  //Start page, where the user gets a list of registered SO and can add new ones
  .when('/', {
    templateUrl: 'templates/index.html', 
    controller: 'indexCtrl',
    resolve: {
      loggedin: checkLoggedin
    }
  })
  .when('/login', {
    templateUrl: 'templates/login.html', 
    controller: 'loginCtrl'
  })
  // do more here
  .otherwise({
      redirectTo: '/'
  });
}]).run(function($rootScope, $http){
//Do some initial tasks or set some values
});