# Unsubscribe from Angular/RxJS subscription

Source: https://tpiros.dev/blog/unsubscribe-from-angular-rxjs-subscription

Angular developers have been getting comfortable with [Observables](https://fullstack-developer.academy/introduction-to-rxjs-and-observables/). We all know we subscribe to HTTP results using `.subscribe()`.

> There are other ways to pull data via HTTP in Angular, but they're not covered here.

The question that matters: when (if ever) should we **unsubscribe**?

An active subscription on a component that Angular's no longer using creates a memory leak. Something's chewing through memory even though nothing needs it, and that memory never gets handed back to the OS.

Let's look at when you need to call unsubscribe and when you can skip it entirely.

# Create a Service

First, a sample service. Imagine an Angular service that greets users:

```typescript

@Injectable()

  private greeting$ = new Subject();

  constructor() {}

  greet(name) {
    this.greeting$.next(`Hello there, ${name}!`);
  }
  getGreeting() {
    return this.greeting$;
  }
}
```

Pass a name to the `greet()` method and you get back `Hello there, Tamas!`.

# Create components

Now let's build two components. One holds the buttons and input for testing. It also displays the second component.

```html
<!-- Main Component -->
<button (click)="destroy()" *ngIf="displayed">Destroy component</button>
<br />
<button (click)="greet(field.value)">Greet!</button>
<input type="text" #field id="name" placeholder="Your name" />

<app-second *ngIf="displayed"></app-second>
```

```typescript
// Main Component

@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.css'],
})

  private displayed = true;
  constructor(private api: ApiService) {}

  greet(value) {
    this.api.greet(value);
  }
}

// Second Component

@Component({
  selector: 'app-second',
  templateUrl: './second.component.html',
  styleUrls: ['./second.component.css'],
})

  constructor(private api: ApiService) {}

  ngOnInit() {
    this.api.getGreeting().subscribe((message) => console.log(`${message}`));
  }
}
```

Quick summary: the main component shows buttons and an input box. It calls `greet()` internally, which hits the service and updates `greeting$`. The second component grabs the greeting value on `ngOnInit`.

The main component also has a button to destroy the second component. Destroying it is simple: yank it from the DOM with `*ngIf` and a boolean.

Here's where things go wrong. Type a name, hit `Greet` a few times. You'll see something like `3 Hello there, Joe!` in the console (the number showing how many times you clicked).

Now click `Destroy component`. Then hit `Greet` again. Watch the console. Messages keep appearing. That shouldn't happen. The component responsible for displaying those messages is gone. The problem: we never unsubscribed from the observable. Classic memory leak.

# Unsubscribe from an observable

Two things need to happen. First, implement the `OnDestroy` lifecycle hook. Second, change how the subscription works.

We'll use `takeUntil`, which emits values until a provided observable fires. We create a "trigger" observable that we complete when the component gets destroyed. This tears down the subscription cleanly.

Here's the updated component:

```typescript
// Second Component

@Component({
  selector: 'app-second',
  templateUrl: './second.component.html',
  styleUrls: ['./second.component.css'],
})

  private unsub: Subject<any> = new Subject();

  constructor(private api: ApiService) {}
  ngOnInit() {
    this.api
      .getGreeting()
      .takeUntil(this.unsub)
      .subscribe((message) => console.log(`${message}`));
  }

  ngOnDestroy() {
    this.unsub.next();
    this.unsub.complete();
  }
}
```

Save and rerun the test. Once the component's destroyed, hitting `Greet` produces nothing in the console. Exactly what we want.

# Unsubscribe from an HTTP subscription

Another common observable pattern in Angular: `HttpClientModule`.

> Note the [difference between Http and HttpClient](https://fullstack-developer.academy/angular-http-vs-httpclient/).

Do we need to unsubscribe from HTTP observables? No. Say we're hitting an API for product data. The service looks like this:

```typescript
// service

@Injectable()

  constructor(private http: HttpClient) {}

  getProducts() {
    return this.http.get('http://localhost:3000/api/products');
  }
}
```

And the updated main component:

```typescript
// Main Component

@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.css'],
})

  private displayed = true;
  @ViewChild(ProductsComponent) private productChild: ProductsComponent;
  constructor(private api: ApiService) {}

  destroy() {
    this.displayed = false;
  }

  checkProductsSubscription() {
    console.log(this.productChild.products);
  }
}
```

With the corresponding template:

```html
<!-- Main Component -->
<button (click)="destroy()" *ngIf="displayed">Destroy component</button>
<button (click)="checkProductsSubscription()">
  Check Products Subscription
</button>

<app-products *ngIf="displayed"></app-products>
```

We're using `@ViewChild` to reach into the Products child component's properties. Click `Check Products Subscription` a few times and you'll always get the product list back. But once the component's destroyed, that button throws an error. The values aren't accessible anymore.

You don't need to call `unsubscribe` explicitly here. Under the hood, Angular uses `XMLHttpRequest()`, which gets garbage collected once its `load` event listener finishes collecting data. Unsubscription happens automatically through garbage collection.
