Tuesday, March 6, 2018

When you use an .subscribe with an Observable in an Angular 4 component you should explictly destroy it.

I won't show the whole of the component, but let's assume that there are import statements. Let's include this one:

import { ISubscription } from 'rxjs/Subscription'

 
 

As public properties on the component itself, let's have:

unsavedAnswers: Observable<Array<SaveAnswerEventModel>>;
unsavedAnswersState: Array<SaveAnswerEventModel>;
unsavedAnswersSubscription: ISubscription;

 
 

Let's use a selector as suggested here to populate these as follows. Note the .subscribe please.

ngOnInit() {
   this.unsavedAnswers = this.store.select(getUnsavedAnswers);
   this.unsavedAnswersSubscription = this.unsavedAnswers.subscribe(result =>
         this.unsavedAnswersState = result);
}

 
 

When the component dies, so too should the .subscribe die. Don't let it hang out to create a memory leak.

ngOnDestroy(){
   this.unsavedAnswersSubscription.unsubscribe();
}

 
 

We might actually use unsavedAnswersState at a button click event like this:

saveUnsavedAnswers(): void {
   console.log(this.unsavedAnswersState);
   let answers = this.unsavedAnswersState.map((model: SaveAnswerEventModel) => {
      let saveAnswerModel = new SaveAnswerModel();
      saveAnswerModel.questionId = model.question.id;
      saveAnswerModel.answer = model.answer;
      saveAnswerModel.skipped = model.skipped;
      return saveAnswerModel;
   });
   this.store.dispatch(new SaveAnswersRequestAction(answers));
}

 
 

This is an example of a scenario wherein you have to use a .subscribe in TypeScript itself in lieu of just using the async pipe in a template which both does the same thing and cleans itself up without you explicitly having to do so. Beware of the potential for a performance hit with this stuff. It's going to feel good until you start eating yourself.

No comments:

Post a Comment