admin管理员组文章数量:1123003
I'm learning with Angular 19. Now I tried to implement a service for authentication, which keeps an _isAuthenticated state as a class property. The service is marked as @injectable and provied in 'root' as the default setting. Then, I injected the service into other components, e.g. a route guard.
The problem is, when the route guard works, it gets a authentication service object from inject(). I would expect that Angular injects the servie as a singleton, however, in my case the obtained service is always a new object. When I set a breakpoint in the constructor of the service, it is always reached when the route guard takes effect. Then, of course only the initial value of the _isAuthenticated state is passed to the guard, which is "false".
This problem has confused me for some days. Any help would be great! Thanks!
My service for authentication:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { BehaviorSubject, catchError, map, Observable, of } from 'rxjs';
import { User } from '../dto/user';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private apiUrl = 'http://192.168.178.39:8080/auth';
private _isAuthenticated = new BehaviorSubject<boolean>(false);
constructor(private http: HttpClient) {
localStorage.removeItem('JWT_Token');
}
login(username: string, password: string ): Observable<boolean> {
return this.http.post<any>(this.apiUrl + '/login', {username, password})
.pipe(
map(response => {
localStorage.setItem('JWT_Token', response.token);
this._isAuthenticated.next(true);
return true;
}),
catchError(error => {
console.log(error);
this.logout();
return of(false);
})
);
}
logout(): void {
localStorage.removeItem('JWT_Token');
this._isAuthenticated.next(false);
}
get isAuthenticated() {
return this._isAuthenticated.value;
}
}
my route guard which injects the service:
import { CanActivateFn } from '@angular/router';
import { AuthService } from '../service/auth.service';
import { inject } from '@angular/core';
export const authGuard: CanActivateFn = (route, state) => {
const authService = inject(AuthService);
let isAuth = authService.isAuthenticated;
return isAuth;
};
The app.routes.ts, where the route guard is put into use:
import { Routes } from '@angular/router';
import { HomeComponent } from './feature/home/homeponent';
import { LoginComponent } from './core/auth/login/loginponent';
import { BookListComponent } from './feature/bookstore/book-list/book-listponent';
import { authGuard } from './core/auth/guard/auth.guard';
export const routes: Routes = [
{path: 'login', component : LoginComponent},
{path: '', redirectTo: 'login', pathMatch : 'full'},
{path: 'home', component : HomeComponent, canActivate : [authGuard]},
{path: 'bookstore', component : BookListComponent, canActivate : [authGuard]},
];
finally, the app.config.ts
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { AuthInterceptor } from './core/auth/intercept/auth.interceptor';
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient(withInterceptorsFromDi()),
{provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true},
]
};
I'm learning with Angular 19. Now I tried to implement a service for authentication, which keeps an _isAuthenticated state as a class property. The service is marked as @injectable and provied in 'root' as the default setting. Then, I injected the service into other components, e.g. a route guard.
The problem is, when the route guard works, it gets a authentication service object from inject(). I would expect that Angular injects the servie as a singleton, however, in my case the obtained service is always a new object. When I set a breakpoint in the constructor of the service, it is always reached when the route guard takes effect. Then, of course only the initial value of the _isAuthenticated state is passed to the guard, which is "false".
This problem has confused me for some days. Any help would be great! Thanks!
My service for authentication:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { BehaviorSubject, catchError, map, Observable, of } from 'rxjs';
import { User } from '../dto/user';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private apiUrl = 'http://192.168.178.39:8080/auth';
private _isAuthenticated = new BehaviorSubject<boolean>(false);
constructor(private http: HttpClient) {
localStorage.removeItem('JWT_Token');
}
login(username: string, password: string ): Observable<boolean> {
return this.http.post<any>(this.apiUrl + '/login', {username, password})
.pipe(
map(response => {
localStorage.setItem('JWT_Token', response.token);
this._isAuthenticated.next(true);
return true;
}),
catchError(error => {
console.log(error);
this.logout();
return of(false);
})
);
}
logout(): void {
localStorage.removeItem('JWT_Token');
this._isAuthenticated.next(false);
}
get isAuthenticated() {
return this._isAuthenticated.value;
}
}
my route guard which injects the service:
import { CanActivateFn } from '@angular/router';
import { AuthService } from '../service/auth.service';
import { inject } from '@angular/core';
export const authGuard: CanActivateFn = (route, state) => {
const authService = inject(AuthService);
let isAuth = authService.isAuthenticated;
return isAuth;
};
The app.routes.ts, where the route guard is put into use:
import { Routes } from '@angular/router';
import { HomeComponent } from './feature/home/home.component';
import { LoginComponent } from './core/auth/login/login.component';
import { BookListComponent } from './feature/bookstore/book-list/book-list.component';
import { authGuard } from './core/auth/guard/auth.guard';
export const routes: Routes = [
{path: 'login', component : LoginComponent},
{path: '', redirectTo: 'login', pathMatch : 'full'},
{path: 'home', component : HomeComponent, canActivate : [authGuard]},
{path: 'bookstore', component : BookListComponent, canActivate : [authGuard]},
];
finally, the app.config.ts
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import { AuthInterceptor } from './core/auth/intercept/auth.interceptor';
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient(withInterceptorsFromDi()),
{provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true},
]
};
Share
Improve this question
asked 58 mins ago
user29062502user29062502
1
New contributor
user29062502 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1 Answer
Reset to default 0private _isAuthenticated = new BehaviorSubject(false); _isAuthenticated$ = this._isAuthenticated.asObservable();
then you either subscribe on the _isAuthenticated$ or await it with const isAuth = await firstValueFrom(auth.isAuthenticated);
As it is atm you only check the initial value with the get property. you never subscribe for changes.
本文标签: Angular 19why an Injectable service is created every time new when it is injectedStack Overflow
版权声明:本文标题:Angular 19 - why an @Injectable service is created every time new when it is injected? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736540346a1944379.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论