Reputation: 3749
In my Angular application, I am implementing 2 services:
These two services depend on each other:
IdleService
)logout
method from the AuthenticationService
to log out the user.This approach is causing a circular dependency problem. Do you have any idea how to avoid it or how to change my actual approach by a better one?
Upvotes: 2
Views: 1256
Reputation: 13406
I would say the auth service is responsible holding, managing, and exposing the state of user authentication. By this I am saying the auth service should not care about user idleness at all. This is the responsibility of the idle service.
So I would create a BehaviorSubject in the auth service that broadcasts the state of the user authentication. The idle service can use the subject to determine when an idle timer needs to start/stop.
export class AuthService {
user: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
logIn(){
// logic to log user in
this.user.next(true);
}
logOut(){
// logic to log user out
this.user.next(false);
}
}
Now the idle service can inject the auth service and determine how to handle the idle timer
export class IdleService {
constructor(private authService: AuthService){
this.authService.user.subscribe(res => {
// watch user authentication state and determine how to handle idle timer
});
}
idleOut(){
this.authService.logOut();
}
}
For this to work you will have to inject the IdleService on app load (for example in the app.component so the IdleService constructor method runs. I am not sure if this is the most elegant solution, but this is the first thing that comes to mind. Here is a very basic stackblitz demoing this concept.
Upvotes: 1
Reputation: 172666
In the book Dependency Injection in .NET 2nd edition (§6.3), Mark Seemann and I describe that Dependency cycles are often caused by Single Responsibility Principle violations. My impression is that this is the case as well in your specific situation. SRP is typically violated when a class has many methods that are not very cohesive.
The solution is to split up either one of the two classes AuthenticationService
and IdleService
(or perhaps even both) into smaller classes.
Upvotes: 2
Reputation: 5379
You could create an observable or a subject in IdleService
which returns a disconnect message if the times goes out. This way, only AuthenticationService
imports IdleService
. For example:
import { IdleService } from './services/idle.service';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthenticationService {
disconnect: Obervable<boolean>;
constructor(private idleService: IdleService) {
this.disconnect = this.idleService.disconnectObservable;
this.disconnect.subscribe(res => {
if (res === true) {
this.logout();
}
});
}
logout() {
//some code here
}
}
In the IdleService
:
import { Observable } from 'rxjs/Observable';
@Injectable()
export class IdleService {
public disconnectObservable: Observable<boolean>;
constructor() {
this.disconnectObservable = new Observable(observer => {
// insert your logic here
setTimeout(() => {
observer.next('true');
}, 1000);
setTimeout(() => {
observer.complete();
}, 3000);
});
}
}
Upvotes: 0