everything I'm reading here: https://angular.io/guide/dependency-injection-in-action makes this seem like it should be possible, but I get this error when trying to call a method on my injected service from another service:
TypeError: Cannot read property 'isLoggedIn' of undefined at CatchSubscriber.handleError [as selector] (project.service.ts:30) at CatchSubscriber.error (catchError.js:29) at TapSubscriber._error (tap.js:56) at TapSubscriber.error (Subscriber.js:55) at MapSubscriber._error (Subscriber.js:75) at MapSubscriber.error (Subscriber.js:55) at FilterSubscriber._error (Subscriber.js:75) at FilterSubscriber.error (Subscriber.js:55) at MergeMapSubscriber.notifyError (OuterSubscriber.js:7) at InnerSubscriber._error (InnerSubscriber.js:14)
Here is my ProjectService
which is injecting my UserService
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Observable, throwError, of } from 'rxjs';
import { catchError, tap, map } from 'rxjs/operators';
import { AuthHeader } from '../../Shared/Helpers/AuthHeader';
import { UserService } from '../../User/Services/user.service';
@Injectable({
providedIn: 'root'
})
export class ProjectService {
constructor(private http: HttpClient, private userService: UserService) {
}
private projectsApiEndPointRoot = '/api/ProjectApi/';
test(): Observable<number> {
return <Observable<number>>this.http.get<number>(this.projectsApiEndPointRoot + "getimages/8", { headers: AuthHeader.getAuthHeader() }).pipe(
tap(data => console.log(data)),
catchError(this.handleError)
);
}
private handleError(err: HttpErrorResponse) {
let errorMessage = '';
if (err.error instanceof ErrorEvent) {
errorMessage = `An error occurred: ${err.error.message}`;
} else {
if (err.status == 401 || err.status == 403) {
console.log(this.userService.isLoggedIn());
}
else {
errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
}
}
console.error(errorMessage);
return throwError(errorMessage);
}
}
The UserService
just has a method that should return boolean whether or not the user is logged in. I use that same method on several components with success, but it's not working when trying to call it from this other service.
Is this not possible to do?
EDIT: adding bits of UserService
for demonstration:
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError, of, BehaviorSubject } from 'rxjs';
import { catchError, tap, map } from 'rxjs/operators';
import { EmailModel } from '../Models/EmailModel';
import { ILoginRequest } from '../Interfaces/ILoginRequest';
import { ILoginResponse } from '../Interfaces/ILoginResponse';
import { IRegistrationRequest } from '../Interfaces/IRegistrationRequest';
import { Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class UserService {
constructor(private http: HttpClient, private router: Router) { }
private usersApiEndPointRoot = 'api/UserApi/';
private loggedIn = false;
...
isLoggedIn() {
return this.loggedIn;
}
private handleError(err: HttpErrorResponse) {
let errorMessage = '';
if (err.error instanceof ErrorEvent) {
errorMessage = `An error occurred: ${err.error.message}`;
} else {
errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
}
console.error(errorMessage);
return throwError(errorMessage);
}
}
The problem is that you're passing the function on the user service. When it is called it the value of this
will be the window.
Instead of passing the function to the catchError
function, use a lambda function so that this will be preserved. Make following change to the test()
method and your problem will be solved:
test(): Observable<number> {
return <Observable<number>>this.http.get<number>(this.projectsApiEndPointRoot +
"getimages/8", { headers: AuthHeader.getAuthHeader() }).pipe(
tap(data => console.log(data)),
catchError(err => this.handleError(err)) // <--
);
}