0

I have this (simplified) service :

@Injectable()
export class DataService {
    constructor(protected url: string) { }

    private handleError(error: Response) {
        console.log(this.url);
        return Observable.throw(new AppError(error));
    }

    getAll() {
        return this.http.get(this.url)
            .map(response => response.json())
            .catch(this.handleError);
    }
}

In handleError function, this.url is undefined. Why ? How can I get the current instance when calling this.handleError from catch ?

I don't see this being a regular use of this, the Observable gets me a lot of TS errors when trying to apply usual JS solutions.

Thanks ahead.

Jeremy Belolo
  • 4,319
  • 6
  • 44
  • 88
  • 1
    `catch(this.handleError.bind(this))` – cartant Oct 19 '17 at 22:01
  • 2
    Or use an arrow function, `catch(() => this.handleError)`. – jonrsharpe Oct 19 '17 at 22:04
  • 1
    Where would the url come from? Services use dependency injection (DI). How would the DI know to pass in a url? – DeborahK Oct 19 '17 at 22:04
  • @DeborahK this service is inherited by others that supply the URL in the `super()` method – Jeremy Belolo Oct 19 '17 at 22:22
  • @cartant thanks it works beautifully ! An answer would get you a ✓ – Jeremy Belolo Oct 19 '17 at 22:23
  • 3
    Possible duplicate of [How to access the correct \`this\` inside a callback?](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – Estus Flask Oct 19 '17 at 22:51
  • @jonrsharpe when trying your solution I get `TS2345:Argument of type '() => (error: Response) => ErrorObservable' is not assignable to parameter of type '(err: any, caught: Observable) => ObservableInput<{}>'. Type '(error: Response) => ErrorObservable' is not assignable to type 'ObservableInput<{}>'. Type '(error: Response) => ErrorObservable' is not assignable to type 'ArrayLike<{}>'. Index signature is missing in type '(error: Response) => ErrorObservable'.` – Jeremy Belolo Oct 20 '17 at 07:55
  • 1
    @JeremyBelolo yes, you'll need to add the right types or at least the parameter in, sorry: `.catch(err => this.handleError(err))`. – jonrsharpe Oct 20 '17 at 07:57

1 Answers1

-1

The constructor of angular service differs from classical constructor you know. And the service shouldn't be ever instantiated by yourself. The Angular itself will instantiate your service and will pass the instance by dependency injection. So because you can't instantiate it and because Angular should do that for you so it can have only services or other Injectables in its argument list so that Angular will aware of it and will be able to pass its instance to your constructor.

If you want to assign something to your url property then you have to add separate method which will do that for you or just make url public and assign directly to it.

But for having it there I'll suggest changing your code to the following

    return this.http.get(this.url)
        .map(response => response.json())
        .catch(error => this.handleError(error));

Just remember that lambda expressions(arrow functions) were added to ES6 especially for context problem. And in ES6 they are more lightweight then functions. But the TypeScript compiler converts all of it to functions. So here the only effect is that context is not changed. But I hope that in the future they will be translated to lambdas and will be much more effective.

hakobpogh
  • 632
  • 6
  • 13
  • It's not right to add a custom parameter like this if it's only supplied by other services extending this one using `super` ? Anyway, I could have showed any of the DI services available to it, instead of the custom parameter, like `http` for example, they were `undefined` as well. With the comment of @cartant though I was able to get it working. – Jeremy Belolo Oct 20 '17 at 07:50
  • Of course, if you want to use it there the @cartant's answer is right. But I'm talking not about this.handleError but about getting url as a part of DI. But I'll prefer to use lambda there instead of binding this to handleError – hakobpogh Oct 20 '17 at 08:01