Search code examples
angularrxjshttpclient

Catching httpClient response inside a service with rxjs


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
  );
}

Solution

  • 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.