Какова наилучшая практика при подписке компонентов на наблюдаемый сервис?[Угловой 2+] - PullRequest
0 голосов
/ 10 декабря 2018

Я создаю приложение, которое получает видеоданные с YouTube.

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

Это то, что у меня есть:

// Component
export class LandingYoutubeComponent implements OnInit {

      constructor(private youtube: YoutubeService) { 
      }

      ngOnInit() {
        this.youtube.getVideos().subscribe(data => console.log(data));
      }
    }

// Service
export class YoutubeService {

  videoSubscription: Observable<any>;
  API_KEY: string = 'someKey';
  CHANNEL_ID: string = 'someID';
  configUrl: string = `https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=${this.CHANNEL_ID}&maxResults=50&order=date&type=video&key=${this.API_KEY}`

  constructor(private http: HttpClient) {
    this.videoSubscription = this.http.get(this.configUrl);  //  create observable for external subscriptions
  }

  getVideos() {
    return this.videoSubscription;
  }
}

И компонент, и служба отделены друг от друга и вставили логику, инкапсулированную каждым классом.

Из того, что я знаюот JS это то, что массивы и и объекты передаются по ссылке, что технически то, что я здесь делаю, но это правильное решение?

Я просто хочу знать, считается ли это наилучшей практикой, и если этонет, как мне это сделать?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Это решение, к которому я пришел в итоге:

// Component
export class LandingYoutubeComponent implements OnInit, OnDestroy {

  videos: any[];

  constructor(private youtube: YoutubeService) { }

  ngOnInit() {
    //  change videos array for every change in service.
    this.youtube.getVideoSubject().subscribe(([v1, v2, v3, v4]: any[]) => {
      this.videos = v1 && v2 && v3 && v4 ? [v1, v2, v3, v4] : [];
      console.log(this.videos);
    });
  }

  ngOnDestroy() {
    this.youtube.getVideoSubject().unsubscribe();
  }
}

// Service
export class YoutubeService {

  private videos: any[];
  private videoSubject: BehaviorSubject<any>;
  private API_KEY: string = 'someKey';
  private CHANNEL_ID: string = 'someId';
  private configUrl: string = `https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=${this.CHANNEL_ID}&maxResults=50&order=date&type=video&key=${this.API_KEY}`

  constructor(private http: HttpClient) {
    this.videos = [];
    this.videoSubject = new BehaviorSubject<any[]>(this.videos);
    this.http.get(this.configUrl).subscribe((videos: any) => {
      this.videos = videos.items;
      this.videoSubject.next(this.videos.slice());  //  emit videos for all subscriptions
    });
  }

  getVideoSubject(): BehaviorSubject<any[]> {
    return this.videoSubject; //  return reference to BehaviorSubject
  }
}

Как уже упоминалось @joh04667, предыдущее решение создавало новый http-запрос для каждой подписки на услугу исходного решения.Итак, чтобы уменьшить количество запросов HTTP, я хотел заполнить свойство службы, создав только один запрос, несмотря на несколько подписок.Я также изменил Observable на унаследованный класс BehaviorSubject.

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

0 голосов
/ 11 декабря 2018

Я бы не стал хранить Observable как собственность службы;это меньше связано с ссылочными типами, как вы упомянули, и больше с дизайном Observable s в целом.

То, что вы делаете, не обязательно плохо;однако Observable - это контракт, который запускается только при подписке.Observable, возвращаемое http.get, - это то, что присваивается вашей службе как собственность;если он никогда не был подписан, никакие http-вызовы не выполняются ... но если три компонента подписываются на этот Observable, будут сделаны три отдельных http-вызова.

Observable, возвращаемый из HttpClient, является холодной, конечной наблюдаемой.Это означает, что он выдаст одно значение и затем отправит сигнал unsubscribe.Если компонент знает это и хочет получить данные только один раз, почему бы просто не вернуть Observable, созданный из http.get напрямую?Таким образом, вызывающая сторона может использовать любое количество Observable операторов на Observable, не затрагивая другие компоненты, пытающиеся получить то же значение.

Наличие Observables в качестве свойства Services (вместо простого возвратановые в методах) действительно имеет смысл для некоторых вещей, но вместо Observables они обычно Subjects.Вот и вся философия дизайна, лежащая в основе государственного управления ngrx-store.Но для холодного, конечного Observables, просто верните Observable вызывающему.

...