【问题标题】:Subscribe to Observable vs subscribe to Subject订阅 Observable 与订阅 Subject
【发布时间】:2019-12-29 08:44:03
【问题描述】:

在 Angular 应用程序中有不同的方法可以从服务器获取数据:

  1. 从服务中获取 Observable 并在组件中订阅它
  2. 在服务创建主题并在组件订阅主题

这两种方法都对我有用,但我不明白应该使用哪种方法。

第一种方法从服务中获取 Observable 并在组件中订阅它

article.service.ts

import { Injectable } from '@angular/core';
import { Article } from '../models/article';
import { AngularFirestore } from '@angular/fire/firestore';
import { map, take } from 'rxjs/operators';
import { Observable, Subject } from 'rxjs';

@Injectable({
  providedIn: "root"
})
export class ArticleService {
  public articlesChanged: Subject<Article[]> = new Subject<Article[]>();
  articles: Article[];

  constructor(private db: AngularFirestore) {}

  get() {
    return this.db.collection('articles').valueChanges({ idField: 'id' });
  }
}

home.component.ts

import { Component, OnInit } from '@angular/core';
import { ArticleService } from 'src/app/services/article.service';
import { Observable, Subscription } from 'rxjs';
import { Article } from 'src/app/models/article';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})

export class HomeComponent implements OnInit {
  articles: Article[];

  constructor(private articlesService: ArticleService) { }

  ngOnInit() {
    this.articlesService.get().subscribe(articles => this.articles = articles as Article[]);
  }
}

第二种方法。 在服务创建Subject并在组件订阅Subject:

article.service.ts

import { Injectable } from '@angular/core';
import { Article } from '../models/article';
import { AngularFirestore } from '@angular/fire/firestore';
import { map, take } from 'rxjs/operators';
import { Observable, Subject } from 'rxjs';

@Injectable({
  providedIn: "root"
})
export class ArticleService {
  public articlesChanged: Subject<Article[]> = new Subject<Article[]>();
  articles: Article[];

  constructor(private db: AngularFirestore) {}

  get(): void {
    this.db
      .collection('articles')
      .valueChanges({ idField: 'id' }).subscribe(articles => {
        this.articles = articles as Article[];
        this.articlesChanged.next(this.articles);
      });
  }
}

home.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ArticleService } from 'src/app/services/article.service';
import { Observable, Subscription } from 'rxjs';
import { Article } from 'src/app/models/article';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})

export class HomeComponent implements OnInit, OnDestroy {
  articlesSubscription: Subscription;
  articles: Article[];

  constructor(private articlesService: ArticleService) { }

  ngOnInit() {
    this.articlesSubscription = this.articlesService.articlesChanged.subscribe(articles => this.articles = articles);
    this.articlesService.get();
  }

  ngOnDestroy(): void {
    this.articlesSubscription.unsubscribe();
  }
}

是否有我应该使用的最佳实践?

【问题讨论】:

标签: angular firebase angular2-services


【解决方案1】:

我们可以说SubjectObservable的一种特殊类型。

Observable:订阅它以获取值。

主题:相同,但您也可以控制要向其中发出的值(可以订阅它也可以发出),您将获得默认值价值。

为了理解 Subject 和 Observable 之间的区别,您需要了解两个不同的概念

  • 数据生产者
  • 数据消费者

根据定义,可观察对象是数据生产者。也就是说,一种可以随时间产生数据的特殊类型。

另一方面,主体可以同时充当 - 数据生产者和数据消费者

这意味着两件事。

  1. 可以订阅主题,就像 observable 一样。
  2. 主题还可以订阅其他可观察对象。

话虽如此,主题和可观察对象之间存在一个主要区别。

主题的所有订阅者共享主题的相同执行。 即当一个主体产生数据时,它的所有订阅者都将收到 相同的数据。这种行为与 observables 不同,其中每个 订阅会导致 observable 的独立执行。

【讨论】:

    【解决方案2】:

    在您的情况下,它可能没有太大区别。 但是,我可以看到使用主题会导致额外的处理,您首先通过valueChanges 订阅获取数据,然后将其推送到主题中,然后从主题中提取数据。这看起来没有必要。

    但是,请考虑另一个需要从 db valueChanges 订阅中获得的相同数据的组件。在这种情况下,您首先从源收集数据,将其推送到主题中,然后订阅同一主题的多个组件都获取数据。 然后,每个组件都可以独立处理数据并做自己的事情。

    例如,假设一个组件触发了一些更改。因此会发生一些处理(比如在后端),并且数据会返回到包含主题的服务。数据现在被推送到主题,并且由于多个组件订阅了该主题,它们都获得了相同的数据。

    正如您所见,这对于以松散耦合方式相互通信的组件非常有帮助。您可以使用这种方法创建松散耦合、灵活、可扩展的系统。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 2018-08-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多