代码之家  ›  专栏  ›  技术社区  ›  mincedMinx

将组件订阅到服务的可观察对象时,最佳实践是什么?[角度2+]

  •  0
  • mincedMinx  · 技术社区  · 7 年前

    我正在构建一个从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 回复  |  直到 7 年前
        1
  •  1
  •   joh04667    7 年前

    我不会留下 Observable 可见的 一般来说。

    你所做的并不一定是坏事;但是 只有在订阅时才运行的合同。这个 http.get 是将什么作为属性分配给您的服务;如果它从未订阅过,则不会进行http调用…但如果有三个组件订阅该属性 ,将进行三个单独的http调用。

    这个 可见的 HttpClient unsubscribe 信号。如果组件知道这一点并且只需要一次数据,为什么不直接返回 可见的 创建自 http.get 直接?这样来电者就可以使用任何数量的 上的操作员 可见的 不会影响其他任何试图获得相同值的组件。

    Observables 有些事情是有道理的,但是 可观察的 他们通常 Subjects 可观察的 ,只需返回 可见的 打电话的人。

        2
  •  0
  •   mincedMinx    7 年前

    我最终得出的解决方案是:

    // 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 .

    所以现在,想要订阅服务的组件现在订阅服务属性中的更改,而不是为每个新订阅构建一个新的请求。