16005

Issues assigning value inside a service function in angular 6

Question:

I kind of lost here, I trying to assign a value to my variable in a function inside my Service, And i cant understand what is the problem. From inside the subscription it seems that its working, but when i try to call it is undefined

I trying to assign value to this variable: private userInfo: any Inside the autoAuthUser() Function

The funny thing that if i console.log the userInfo from my logout function, It showing the value

This is my service:

import { Injectable } from "@angular/core"; import { HttpClient, HttpHeaders } from "@angular/common/http"; import { Subject } from "rxjs"; import { Router } from "@angular/router"; import { SignUpData } from "../models/sign-up.model"; import { LogInData } from "../models/log-in.model"; import { User } from "../models/user"; import { computeStyle } from "../../../node_modules/@angular/animations/browser/src/util"; import { TouchSequence } from "../../../node_modules/@types/selenium-webdriver"; @Injectable({ providedIn: "root" }) export class AuthService { private isAuthenticated = false private token: string private authStatusListner = new Subject<boolean>() private tokenTimer: any private isAdmin: boolean private userInfo: any signupUrl = "http://localhost:3000/signup"; loginUrl = "http://localhost:3000/login" constructor(private http: HttpClient, private router: Router) { } getToken() { return this.token } checkIfAdmin() { return this.isAdmin } getAuthStatus() { return this.isAuthenticated } getAuthStatusListner() { return this.authStatusListner.asObservable() } // Cheacking if the user have the login token in the local storage for autoLogin and the exparation date autoAuthUser() { const AuthInformation = this.getAuthData() if (!AuthInformation) { return } const now = new Date(); const expairesIn = AuthInformation.expirationDate.getTime() - now.getTime(); if (expairesIn > 0) { this.token = AuthInformation.token this.setAuthTimer(expairesIn / 1000) this.autoLogin().subscribe(user => { this.userInfo = user console.log(this.userInfo) }) this.authStatusListner.next(true) this.isAuthenticated = true } } getUserInfo() { if (this.token) { console.log(this.userInfo) return this.userInfo } } createUser(name: string, email: string, password: string) { const authData: SignUpData = { name: name, email: email, password: password } this.http.post(this.signupUrl, authData) .subscribe(response => { }); } autoLogin() { return this.http.get<{ user: any }>(this.loginUrl) } login(email: string, password) { const authData: LogInData = { email: email, password: password } this.http.post<{ token: string, expiresIn: number, isAdmin: boolean, user: any }>(this.loginUrl, authData) .subscribe(response => { const token = response.token this.token = token; if (token) { if (response.isAdmin) { this.isAdmin = response.isAdmin } this.userInfo = response.user const expiersInDuration = response.expiresIn this.setAuthTimer(expiersInDuration) this.isAuthenticated = true this.authStatusListner.next(true); const now = new Date; const expirationDate = new Date(now.getTime() + expiersInDuration * 1000) this.saveAuthData(token, expirationDate) this.router.navigate(['/user']) } }); } // User logout logout() { this.token = null this.isAuthenticated = false this.isAdmin = false this.authStatusListner.next(false) clearTimeout(this.tokenTimer) this.clearAuthData() this.router.navigate(['/user']) console.log(this.userInfo) } // Setting the timer for the token expiration private setAuthTimer(duration: number) { this.tokenTimer = setTimeout(() => { this.logout(); }, duration * 1000) } // Setting the Auth token in the local storage private saveAuthData(token: string, expirationDate: Date) { localStorage.setItem("token", token) localStorage.setItem("expiration", expirationDate.toISOString()) } // Clearing the token from local storage in logout private clearAuthData() { localStorage.removeItem('token') localStorage.removeItem('expiration') } // Geting the login token if it exist in the user local storage private getAuthData() { const token = localStorage.getItem("token"); const expirationDate = localStorage.getItem("expiration") if (!token || !expirationDate) { return } return { token: token, expirationDate: new Date(expirationDate) } } // ******* Loading the token from local storage in the app component }

[edit]

Calling the the service functions in the component

App component:

import { Component, OnInit } from '@angular/core'; import { AuthService } from './services/auth.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { constructor(private authService: AuthService){} ngOnInit(){ this.authService.autoAuthUser() } }

Header component:

import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'; import { Movies } from '../models/movies.model'; import { MoviesService } from '../services/movies.service'; import { FilterPipe } from 'ngx-filter-pipe'; import { DomSanitizer } from '@angular/platform-browser'; import { AuthService } from '../services/auth.service'; import { FormControl, Validators, NgForm, FormGroup } from '@angular/forms'; import { Subscription } from 'rxjs'; import { ModalDirective } from "angular-bootstrap-md"; import { User } from '../models/user'; @Component({ selector: 'app-header', templateUrl: './header.component.html', styleUrls: ['./header.component.css'], }) export class HeaderComponent implements OnInit, OnDestroy { @ViewChild('signUpModal') signUpModal: ModalDirective; @ViewChild('logInModal') logInModal: ModalDirective; //Admincheck isAdmin = false userData: any //Spinners loginSpinner = false signUpSpinner = false //Authintications cheack userIsAuthinticated = false //Movies array for the search movies: Movies[] //Login Form loginForm: FormGroup //SignUp form signUpForm: FormGroup private authListnerSubs: Subscription; constructor(private movieService: MoviesService, private filterPipe: FilterPipe, public sanitizer: DomSanitizer, private authService: AuthService) { } sanitize(url: string) { return this.sanitizer.bypassSecurityTrustUrl('http://localhost:3000/' + url); } ngOnInit() { this.isAdmin = this.authService.checkIfAdmin() this.movieService.getAllMovies() .subscribe( (movies: Movies[]) => (this.movies = movies) ) this.userData = this.authService.getUserInfo() this.userIsAuthinticated = this.authService.getAuthStatus() this.authService.getUserInfo() this.authListnerSubs = this.authService.getAuthStatusListner() .subscribe(isAuthonticated => { this.userIsAuthinticated = isAuthonticated if(this.userIsAuthinticated){ console.log(this.userData) this.loginSpinner = false this.logInModal.hide(); this.loginForm.reset() } this.loginSpinner = false });

Answer1:

Suresh has correctly pointed out your issue in the comments, you send off an async call to autoAuthUser in your AppComponent and, before it has completed, you are sending off a call to getUserInfo in your HeaderComponent. You already have all the plumbing to make this work, you just need to rearrange your code.

Move this.authStatusListner.next(true) inside the callback from autoLogin:

autoAuthUser() { const AuthInformation = this.getAuthData() if (!AuthInformation) { return } const now = new Date(); const expairesIn = AuthInformation.expirationDate.getTime() - now.getTime(); if (expairesIn > 0) { this.token = AuthInformation.token this.setAuthTimer(expairesIn / 1000) this.autoLogin().subscribe(user => { this.userInfo = user console.log(this.userInfo) this.authStatusListner.next(true) }) this.isAuthenticated = true } }

Don't call getUserInfo until after getAuthStatusListener has returned:

this.authListnerSubs = this.authService.getAuthStatusListner() .subscribe(isAuthonticated => { this.authService.getUserInfo() this.userIsAuthinticated = isAuthonticated if(this.userIsAuthinticated){ console.log(this.userData) this.loginSpinner = false this.logInModal.hide(); this.loginForm.reset() } this.loginSpinner = false });

Recommend

  • Symfony2 getUser() in Listener Class from Security Context failing although Token exists
  • Uploading google drive is giving exception
  • Play framework and ionic for mobile I need Security without cookies but token
  • Getting the OAUTH2 Token
  • Google Play Services: TokenActivity appears empty when asking for auth
  • Upload video to twitvid
  • Symfony2 User password become empty after calling service
  • Unable to exchange cookie between Spring and Angular2
  • RxJava 2 / Retrofit 2 - NetworkOnMainThreadException
  • Telegram Bot send Message to bot
  • How to pass user informations to a template using Symfony2 and FosUserBundle
  • Is the firebase access token refreshed automatically?
  • promise.all not access in rejection function
  • How to translate specific content in website
  • Utf-8 url get with curl
  • Symfony dependency injection in twig extension
  • Lock out user with maxInvalidPasswordAttempts not work
  • How to check dictionary value is empty or not
  • IIS Session timeout and Forms Authentication loop
  • csrf-token POST 405 (Method Not Allowed) Laravel
  • Async setup of environment with Jest
  • Prevent ASP.NET textbox within a form from submitting the form
  • Getting 403: Forbidden: Access is Denied when users closes logged in session accidentally
  • Wait for subscription to complete
  • Authentication - JavaScript - Logout issue
  • CORS with socket.io
  • (Tcl/Expect) clear screen after exit
  • mave 3.2 not able to access local nexus instance return 502 code
  • unable to get jsonEncode in magento2
  • Tomcat memory Leak
  • Spring boot 2.0.0.M4 required a bean named 'entityManagerFactory' that could not be found
  • How can I set a binding to a Combox in a UserControl?
  • Create DicomImage from scratch using Dcmtk
  • Django rest serializer Breaks when data exists
  • Cannot resolve symbol 'MyApi'
  • Recording logins for password protected directories
  • Is there any way to access browser form field suggestions from JavaScript?
  • Getting error when using KSoap library to consume .NET web services
  • Angular 2 constructor injection vs direct access