Angular - Как получить данные из подписанного сервиса несколько раз и не перезаписать предыдущие результаты - PullRequest
1 голос
/ 29 мая 2020

У меня есть услуга, которая имеет следующий метод:

room-service.ts

@Injectable()
export class RoomService {
  private readonly _equipment: BehaviorSubject<EquipmentDto[]> = new BehaviorSubject([]);
  public equipment$ = this._equipment.asObservable();

  getEquipmentForRoom(roomId: number) {
    this.restService.getEquipmentForRoom(roomId).subscribe(res => {
      this._equipment.next(res);
    });
  }

room-component.ts:

@Component()
export class RoomsComponent implements OnInit {
  @Input() room: RoomEntity;
  equipment$: Observable < EquipmentDto[] > ;
  equipmentList: Array < EquipmentDto > ;

  constructor(private equipmentService: EquipmentService) {}

  ngOnInit() {
      this.equipment$ = this.equipmentService.equipment$;
      this.equipmentService.getEquipmentForRoom(this.room.id);

      this.equipment$.subscribe(items => {
        this.equipmentList = items;
      });

room-component . html

<div *ngFor="let eq of room.equipmentList">
    <!-- list my equipment here -->
</div>

Теперь у меня есть родительский компонент, который содержит несколько компонентов комнаты (они добавляются программно в зависимости от количества комнат). В любом случае, перечень оборудования для каждой комнаты одинаковый. Похоже, что после подписки данные в первых компонентах перезаписываются компонентом, созданным как последний.

Мой вопрос в том, как я могу получить правильные данные для каждой из комнат, используя наблюдаемый из моей службы?

Ответы [ 4 ]

1 голос
/ 29 мая 2020

попытаться построить трубы вместо подписок

@Injectable()    
export class RoomService {
      // return an observable.
      getEquipmentForRoom$(roomId: number) {
        return this.restService.getEquipmentForRoom(roomId);
      }
@Component()
export class RoomsComponent implements OnInit {
  @Input() room: RoomEntity;
  equipment$: Observable<EquipmentDto[]>;

  constructor(private equipmentService: EquipmentService){}

  ngOnInit() {
    // simply share observable.
    this.equipment$ = this.equipmentService.getEquipmentForRoom$(this.room.id);
  });
  <div *ngFor="let eq of equipment$ | async"> <!-- add async here -->
      <!-- list my equipment here -->
  </div>
1 голос
/ 29 мая 2020

Вы можете использовать этот подход с одним BehaviorSubject только тогда, когда ваши данные являются единственным источником этих данных.

Вместо этого вы можете изменить свой getEquipmentForRoom(roomId: number) следующим образом:

getEquipmentForRoom(roomId: number) {
    return this.restService.getEquipmentForRoom(roomId);
}

А затем подпишитесь на него в комментарии:

this.equipmentService.getEquipmentForRoom(this.room.id).subscribe(items => {
  this.equipmentList = items;
});

И я согласен с Александром, этот компонент должен быть тупым, насколько это возможно.

0 голосов
/ 29 мая 2020

Добавление к ответу Александра .

Проблема в том, что вы подписываетесь на один и тот же BehaviourSubject для всех компонентов, а компоненты используют последние roomData, которые испускается BehaviourSubject, который будет последним RoomComponent.

Это будет работать, если BehaviuorSubject будет содержать все комнаты, которые выбираются родительским компонентом, и передавать данные каждой комнаты каждому RoomComponent с использованием @Input.

0 голосов
/ 29 мая 2020

Вы можете получить данные один раз в родительском компоненте и передать их дочерним компонентам. Этот дочерний компонент (RoomsComponent) должен быть тупым и не выполнять запросы

...