Как лучше распределять данные в карте / объекте / массиве по сервисам между Angular компонентами? - PullRequest
0 голосов
/ 28 апреля 2020

Я учусь angular сейчас. Когда дело доходит до обмена данными с использованием сервиса, многие рекомендуют использовать Subject, например, BehaviorSubject . Но должны ли мы делать это все время?

@Injectable({
  providedIn: 'root'
})
export class DataService {

  private imageUrls = new Map<number, string>();
  public imageUrlsSubject = new BehaviorSubject(this.imageUrls);

   public size(): number {
     return this.imageUrls.size;
   }

   public set(id: number, url: string): void {
     this.imageUrls.set(id, url);
     this.imageUrlsSubject.next(this.imageUrls);
   }

   public get(id: number): string {
     return this.imageUrls.get(id);
    }


    public has(id: number): boolean {
      return this.imageUrls.has(id);
    }
}

Я написал такой сервис, следуя этой практике. Это заставляет меня задуматься: действительно ли нам нужен предмет здесь? Могу ли я просто избавиться от imageUrlsSubject в контексте, что другому компоненту просто нужно использовать карту в DOM.

<img   
  *ngIf="dataService.has(row.id)" 
  [src]="dataService.get(row.id).url">

А в другом компоненте, возможно, мне просто нужно вызвать dogDataService.set , чтобы обновить карту.

this.dataService.set(id, url);

Если я избавлюсь от предмета, принесет ли он здесь некоторые потенциальные недостатки?

Спасибо!

1 Ответ

0 голосов
/ 28 апреля 2020

Вы используете только свой BehaviorSubject, но ваш получатель не полагается на него. Ваша текущая услуга полностью синхронизирована с потребителями, и «да», то, как вы запрограммировали ее сейчас, imageUrlsSubject на самом деле не нужно.

Истинное преимущество использования субъекта заключается в том, что вы можете предоставьте это как наблюдаемый в другие места! Вместо того, чтобы люди могли получить доступ только к текущему значению imageUrls, они могут получить доступ к текущим и всем будущим значениям imageUrls! Им дается поток вместо снимка.

Затем у вас есть 3 варианта дизайна:

  • Всегда возвращать наблюдаемое. Люди должны передать его и take(1), если им нужен снимок.
  • Всегда возвращать наблюдаемую, но добавить сокращенную функцию snap, которая возвращает текущее значение.
  • Всегда возвращать снимок ( как в настоящее время в вашем коде) и добавьте функцию watch, которая возвращает Observable.

Я бы go еще дальше и сказал бы, что вам не следует хранить отдельное свойство imageUrls и вместо этого полагайтесь на imageUrlsSubject.value (только для объектов поведения). Я только рекомендую это, чтобы вы A) с меньшей вероятностью забыли subject.next(newValue), когда вы измените свое значение B), чтобы снова напомнить вам, что вы должны использовать свой предмет; p

Вот адаптированный пример, который поддерживает синхронное поведение по умолчанию get и добавляет асинхронный watch.

@Injectable({
  providedIn: 'root'
})
export class DataService {
  public imageUrlsSubject = new BehaviorSubject(new Map<number, string>());

   public size(): number {
     return this.imageUrlsSubject.value.size;
   }

   public set(id: number, url: string): void {
     this.imageUrlsSubject.value.set(id,url);
     this.imageUrlsSubject.next(this.imageUrlsSubject.value);
   }

   public get(id: number): string {
     return this.imageUrlsSubject.value.get(id);
    }


    public has(id: number): boolean {
      return this.imageUrlsSubject.value.has(id);
    }

    public watch(): Observable<Map<number, string>> {
      return this.imageUrlsSubject.asObservable();
    }
}

Теперь в другом месте вашего кода вы можете подписаться на любые изменения в вашей карте, вы можете передать его, передать труба / наблюдаемая вокруг, ...

...