RxJS Subjects em Angular
Tags: rxjs, angular, webdev, tutorial
Published: 2023-08-25 23:51:03

Os Subjects são uma parte crucial da biblioteca RxJS e são frequentemente usados em aplicações Angular para gerenciar e manipular fluxos de dados reativos. Vamos mergulhar nas diferenças entre os diferentes tipos de Subjects e ver exemplos práticos de como eles são aplicados em aplicações Angular.

## Diferenças entre Subject, BehaviorSubject, ReplaySubject e AsyncSubject

### 1. Subject
- **Definição**: Um Subject é tanto um Observable quanto um Observer. Isso significa que você pode tanto emitir valores para ele quanto se inscrever nele.
- **Características**: Ao se inscrever em um Subject depois que ele emitiu valores, você não receberá os valores anteriores. Você só receberá os valores emitidos após a inscrição.

### 2. BehaviorSubject
- **Definição**: Um BehaviorSubject é semelhante a um Subject, mas armazena o último valor emitido. Assim, cada novo inscrito receberá imediatamente o último valor emitido antes da sua inscrição.
- **Características**: Ao criar um BehaviorSubject, você precisa fornecer um valor inicial. Esse será o valor que os novos inscritos receberão se não houver outro valor emitido.

### 3. ReplaySubject
- **Definição**: Um ReplaySubject grava os valores emitidos e pode reemitir esses valores para novos inscritos.
- **Características**: Ao criar um ReplaySubject, você pode especificar quantos valores recentes deseja armazenar e reemitir para novos inscritos.

### 4. AsyncSubject
- **Definição**: Um AsyncSubject é semelhante ao BehaviorSubject no sentido de que armazena o último valor. No entanto, o AsyncSubject só emite o valor no momento da conclusão.
- **Características**: Se você se inscrever em um AsyncSubject e ele já tiver sido concluído, receberá imediatamente o último valor emitido.

## Exemplos Práticos em Aplicações Angular

### 1. Subject

Imagine um serviço que informa quando um usuário foi atualizado:

```typescript
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  userUpdated = new Subject<void>();

  updateUser() {
    // Lógica de atualização do usuário
    this.userUpdated.next();
  }
}
```

Em um componente:

```typescript
@Component({
  // ...
})
export class UserComponent implements OnInit {
  constructor(private userService: UserService) {}

  ngOnInit() {
    this.userService.userUpdated.subscribe(() => {
      console.log('Usuário atualizado!');
    });
  }
}
```

### 2. BehaviorSubject

Utilizado para armazenar o estado atual do usuário:

```typescript
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private currentUser = new BehaviorSubject<User>({ name: 'Guest' });

  getCurrentUser() {
    return this.currentUser.asObservable();
  }

  updateCurrentUser(newUser: User) {
    this.currentUser.next(newUser);
  }
}
```

### 3. ReplaySubject

Perfeito para armazenar um histórico de mensagens em um chat:

```typescript
import { ReplaySubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ChatService {
  private messages = new ReplaySubject<string>(5); // Armazena as últimas 5 mensagens

  getMessages() {
    return this.messages.asObservable();
  }

  addMessage(message: string) {
    this.messages.next(message);
  }
}
```

### 4. AsyncSubject

Útil para ações que só nos interessam no final, como um pedido HTTP:

```typescript
import { AsyncSubject } from 'rxjs';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  private dataSubject = new AsyncSubject<Data>();

  constructor(private http: HttpClient) {}

  fetchData() {
    this.http.get<Data>('url').subscribe(data => {
      this.dataSubject.next(data);
      this.dataSubject.complete();
    });

    return this.dataSubject.asObservable();
  }
}
```

Ao usar o AsyncSubject neste exemplo, os inscritos só receberão um valor quando o pedido HTTP for concluído.

## Conclusão

Os Subjects e suas variantes oferecem uma flexibilidade incrível ao trabalhar com fluxos de dados reativos em Angular. Escolher o tipo correto de Subject pode simplificar seu código e tornar sua aplicação mais eficiente.