I have a LoginComponent (form for the credentials) and a LoginService for calling my api with an httpClient.
Usually in my services i'm returning the call so I can subscribe to it inside my component.
For example:
doSomething() {
return this.http.post<any>(...);
}
The problem here is that I need to subscribe to the call both inside my component and my service because I want to handle the storage there.
I've found this solution in a tutorial but I think it's not the most appropriate way and maybe there's a better solution using rxjs pipe.
AuthService:
login(userName: string, password: string, onSuccess: () => void, onError: (error) => void) {
this.http.post("https://localhost:5001/api/auth/login", {userName: userName, password: password})
.subscribe(response => {
let token = (<any>response).token;
localStorage.setItem("jwt", token);
this.readUserFromLocalStorage();
onSuccess();
}, err => {
onError(err);
});
}
And inside my component
login() {
this.auth.login(this.userName, this.password,
() => this.router.navigateByUrl('/'),
(error) => this.invalidLogin = true
);
}
In your auth service you could use a tap
inside a pipe
.
A tap
is a really good way to do something with the response without modifying it. (If you do need to modify it on the way to your component then you should probably use a map
function.
this.http.post("https://localhost:5001/api/auth/login", {userName: userName, password: password})
.pipe(tap(response => {
let token = (<any>response).token;
localStorage.setItem("jwt", token);
this.readUserFromLocalStorage();
}));
}
Then you could subscribe in your component.
login() {
this.auth.login(this.userName, this.password).subscribe(() => {
this.router.navigateByUrl('/')
},
(error) => this.invalidLogin = true
}
This way you don't need to have a callback to your service! Hope this helps.