订阅可观察vs订阅主题

时间:2019-08-24 08:08:39

标签: angular firebase angular2-services

在Angular应用程序中有多种从服务器获取数据的方法:

  1. 从服务中获取可观察的内容并在组件上订阅
  2. 在服务上创建主题并在组件上订阅主题

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

第一种方法从服务中获取可观察到的内容,并在组件上订阅

article.service.ts

<table id="table" border="1">
  <tr>
    <th></th>
    <th>First Name</th>
    <th>Last Name</th>
    <th>Age</th>
    <th>edit</th>
  </tr>
  <tr>
    <td><input type="checkbox" class="select"></td>
    <td>A1</td>
    <td>B1</td>
    <td>10</td>
    <td><input type="button" value="edit" class="edit"></td>
  </tr>
  <tr>
    <td><input type="checkbox" class="select"></td>
    <td>A3</td>
    <td>B3</td>
    <td>30</td>
    <td><input type="button" value="edit" class="edit"></td>
  </tr>
  <tr>
    <td><input type="checkbox" class="select"></td>
    <td>A2</td>
    <td>B2</td>
    <td>20</td>
    <td><input type="button" value="edit" class="edit"></td>
  </tr>
</table>
<button onclick="deleteRow();">Remove</button>

home.component.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' });
  }
}

第二种方法。 在服务中创建主题并在组件处订阅主题:

article.service.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[]);
  }
}

home.component.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);
      });
  }
}

我应该使用最佳实践吗?

2 个答案:

答案 0 :(得分:2)

  

我们可以说主题可观察的一种特殊类型。

可观察:订阅它即可获取值。

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

为了了解主题和可观察对象之间的区别,您需要了解两个不同的概念

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

根据定义,可观察的是数据生产者。尽管这是一种可以随时间产生数据的特殊类型。

另一方面,主题可以同时充当– 数据生产者和数据使用者

这意味着两件事。

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

话虽这么说,对象和可观察对象之间存在一个关键差异。

  

主题的所有订阅者共享该主题的相同执行。   即,当主题产生数据时,其所有订阅者都将收到   相同的数据。这种行为不同于可观察到的行为,可观察到的行为   订阅会导致可观察对象的独立执行。

答案 1 :(得分:1)

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

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

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

如您所见,这在组件之间以松散耦合的方式相互通信非常有用。您可以使用这种方法创建一个松耦合,灵活,可扩展的系统。