Sergiy Sergiy - 1 year ago 91
TypeScript Question

Angular 2/4 Observables

I am a beginner with Angular 2 and have some questions:

Q#1 I have a method (which is placed in component), for instance "Get". It returns Observable with Array of strings. In this method I use angular's HTTP module which sends get request to backend:

this.http.get("some_URL").map(resp =><Array<string>>resp.json()).subscribe(items =>{
this.items = items; //private component's variable
this.subject.next(this.items); //private component's subject
});
return this.subject.asObservable(); //returns subject as observable


So, what I am doing here is just send GET request and before getting the result I return my Subject as Observable. Some code, which calls Get method subscribes on my "subject as observable", and when Get method gets result from backend it calls next and passes there the data which it got. Please correct me if I wrong, but I hope I have a clear understanding of how to use Observables.

Q#2 Lets assume I have another method GetById which accepts id:number and returns string. Would it be correct if I created a local BehaviorSubject variable in this method? So, every time when someone calls this method the new BehaviorSubject will be created and returned for subscription. Can it somehow has a bad influence on memory or performance?

var tmpSubject: BehaviorSubject<string>;

this.http.get("some_URL").map(resp => resp.json()).subscribe(item =>{
tmpSubject.next(item);
});

return tmpSubject.asObservable();


I would appreciate any help. Thanks!

Answer Source

Q1:

There is a much better way of doing this. Do something like this:

let observable = this.http.get("some_URL").map(resp =><Array<string>>resp.json()).cache();

let subscription = observable.subscribe(items =>{
    this.items = items; //private component's variable
    this.subject.next(this.items); //private component's subject
});

return observable; //returns subject as observable

In Q2, there is no need for you to create a BehaviouralSubject either. You rarely create observables yourself. And http.get returns an observable. So just use it! If you want to call get once but subscribe to it in multiple places, the use something like cache (I think it might have been droppen in newer versions of rxjs, but there is an alternative).

Also, a good pattern is to unsubscribe to your subscriptions. So subscribing should only be done in Angular @Components and you should add .unsubscribe to OnDestroy hook. This gives a great explanation of the issue in detail: http://brianflove.com/2016/12/11/anguar-2-unsubscribe-observables/

And in general, the best pattern I found to be is that you create a service class, that exposes get/post/whatever methods, that all return Observables of any kind. Then you only subscribe to them in your components (or directives). They have OnDestroy hooks that will allow you to unsubscribe and not leak memory.

It would look something like:

export class SomeService {

    function getSomething(param: any): Observable<SomeType> { ... }

}

...

@Component
export class SomeComponent extends OnDestroy {

    subscription: Subscription;

    constructor(private service: SomeService) {
        this.subscription = service.getSomething(123).subscribe(...);
    }


    function ngOnDestroy(){
        if(this.subscription) {
            this.subscription.unsubcribe();
        }
    }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download