Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't use services inside a catchError function

I want to have a generic way of handling exceptions, expecially 401's received from the backend. When I don't extract the catchError content, it works fine. However if I simply extract it to a specific function, then nothing gets injected in that function:

return this.http.request<T>(new HttpRequest('POST', this.appConfig.baseApiPath + url, file, {
            reportProgress: true,
            headers: headers,
            params: urlParams
        })).pipe(
            catchError((err) => {
                if (err.status === 401) {
                    this.router.navigateByUrl('/login?expired=true');
                }
                return Observable.throw(err || 'Server error')
            })
        );

This works! However I wanted to handle this redirect code in a function in order to reuse it by other methods.

Here I exported that into a function:

    return this.http.request<T>(new HttpRequest('POST', this.appConfig.baseApiPath + url, file, {
        reportProgress: true,
        headers: headers,
        params: urlParams
    })).pipe(
        catchError(this.handleHttpError),
    );

handleHttpError(error: HttpErrorResponse) {
    if (error.status === 401) {
        this.router.navigateByUrl('/login?expired=true'); --> router is null!
    }
    return Observable.throw(error || 'Server error')
}

And that's where router (as well as other constructor injected services) are null if I use that way of working... could you suggest why?

like image 475
Qualaelay Avatar asked Aug 25 '18 19:08

Qualaelay


2 Answers

The reason is that you're losing context. When function is declared in such way this keyword is about scope of the function, not the whole class. Not to lose context you shoud use an arrow function:

handleHttpError = (error: HttpErrorResponse) => {
    if (error.status === 401) {
        this.router.navigateByUrl('/login?expired=true');
    }
    return Observable.throw(error || 'Server error')
}
like image 105
dsych Avatar answered Sep 23 '22 03:09

dsych


a better approach is to bind 'this' to your call:

catchError(this.handleHttpError.bind(this))
like image 34
Avi Avatar answered Sep 21 '22 03:09

Avi