Como faço para armazenar um contexto de usuário atual no AngularJS?
92
Eu tenho um AuthService, que registra um usuário, ele retorna um objeto json do usuário. O que eu quero fazer é definir esse objeto e ter todas as alterações refletidas no aplicativo (estado conectado / desconectado) sem ter que atualizar a página.
Você pode então fazer referência a isso em qualquer um de seus controladores. O código a seguir observa as alterações em um valor do serviço (chamando a função especificada) e, em seguida, sincroniza os valores alterados com o escopo.
E então, é claro, você pode usar essas informações da maneira que achar necessário; por exemplo, em diretivas, em modelos, etc. Você pode repetir isso (personalizado para o que você precisa fazer) em seus controladores de menu, etc. Tudo será atualizado automaticamente quando você alterar o estado no serviço.
Qualquer coisa mais específica depende da sua implementação.
@ChrisNicola Na verdade, no AngularJS todos os serviços são singletons. Portanto, o serviço é criado na primeira vez que é solicitado (ou seja, por um controlador ou outro serviço) e todas as solicitações subsequentes retornam exatamente a mesma instância.
Josh David Miller
2
Pode ser, mas como uma função, podemos remover os detalhes internos de como armazenamos essas informações da API pública e na API privada. Isso torna a refatoração posterior muito mais fácil. Mas a função ainda retornaria um booleano.
Josh David Miller,
7
Esta pode ser uma pergunta estúpida ... mas o que acontece se o usuário atualizar a página - as informações de login foram perdidas?
Tomba
10
@Tomba Essa é uma boa pergunta. :-) Na verdade, a informação se perde na atualização. Normalmente, você deseja armazenar algumas informações da sessão em um cookie. Essas informações da sessão também podem ser verificadas ao configurar o AuthService. Isso ajuda não apenas para atualizações de página, mas para alguém abrindo um link em uma nova guia.
Josh David Miller
2
@PixMach Você está 100% certo sobre a curva de aprendizado. Sua pergunta vai depender muito do caso específico, mas aqui estão alguns padrões gerais. Mantenha a separação de preocupações: a IU relacionada ao início de um login é separada da própria auth, que é separada do estado da auth, que é separada de qualquer menu que possa depender desse estado. Nav / menu são geralmente mais bem tratados por um único controlador, e estados aninhados (a la ui-router) e resoluções de rota são uma boa maneira de manter os controles de autenticação DRY. O que você escreveu parece certo.
Josh David Miller
5
Eu corrigiria a boa resposta de Josh acrescentando que, como um AuthService é tipicamente do interesse de qualquer pessoa (digamos, qualquer um, exceto a visualização de login deve desaparecer se ninguém estiver conectado), talvez uma alternativa mais simples seja notificar as partes interessadas usando $rootScope.$broadcast('loginStatusChanged', isLoggedIn);(1 ) (2), enquanto as partes interessadas (como controladores) ouviriam usando $scope.$on('loginStatusChanged', function (event, isLoggedIn) { $scope.isLoggedIn = isLoggedIn; }.
(1) $rootScopesendo injetado como um argumento do serviço
(2) Observe que, no caso provável de uma operação de login assíncrona, você desejará notificar o Angular que a transmissão mudará as coisas, incluindo-o em uma $rootScope.$apply()função.
Agora, por falar em manter o contexto do usuário em todos / muitos controladores, você pode não gostar de ouvir as alterações de login em todos eles e pode preferir ouvir apenas em um controlador de login superior, adicionando então outros controladores com reconhecimento de login como filhos / controladores embutidos deste. Dessa forma, o controlador filho será capaz de ver as propriedades herdadas do parent $ scope, como o contexto do usuário.
Votos negativos para explicação incorreta da função de fábrica. Esse mal-entendido já foi abordado neste comentário meses antes de você postar sua resposta.
AuthService
. Isso ajuda não apenas para atualizações de página, mas para alguém abrindo um link em uma nova guia.ui-router
) e resoluções de rota são uma boa maneira de manter os controles de autenticação DRY. O que você escreveu parece certo.Eu corrigiria a boa resposta de Josh acrescentando que, como um AuthService é tipicamente do interesse de qualquer pessoa (digamos, qualquer um, exceto a visualização de login deve desaparecer se ninguém estiver conectado), talvez uma alternativa mais simples seja notificar as partes interessadas usando
$rootScope.$broadcast('loginStatusChanged', isLoggedIn);
(1 ) (2), enquanto as partes interessadas (como controladores) ouviriam usando$scope.$on('loginStatusChanged', function (event, isLoggedIn) { $scope.isLoggedIn = isLoggedIn; }
.(1)
$rootScope
sendo injetado como um argumento do serviço(2) Observe que, no caso provável de uma operação de login assíncrona, você desejará notificar o Angular que a transmissão mudará as coisas, incluindo-o em uma
$rootScope.$apply()
função.Agora, por falar em manter o contexto do usuário em todos / muitos controladores, você pode não gostar de ouvir as alterações de login em todos eles e pode preferir ouvir apenas em um controlador de login superior, adicionando então outros controladores com reconhecimento de login como filhos / controladores embutidos deste. Dessa forma, o controlador filho será capaz de ver as propriedades herdadas do parent $ scope, como o contexto do usuário.
fonte