简体   繁体   English

订阅 Observable 与订阅 Subject

[英]Subscribe to Observable vs subscribe to Subject

There are different methods to get data from server in Angular application:在 Angular 应用程序中,有多种方法可以从服务器获取数据:

  1. Get Observable from the service and subscribe to it at component从服务中获取 Observable 并在组件处订阅它
  2. Create Subject at the service and subscribe to the Subject at component在服务上创建主题并在组件上订阅主题

Both of this methods work for me but I can't understand which should I use.这两种方法都对我有用,但我不明白我应该使用哪种方法。

First method .第一种方法 Get Observable from the service and subscribe to it at component :从服务中获取 Observable 并在组件处订阅它

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

Second method.第二种方法。 Create Subject at the service and subscribe to the Subject at component:在服务上创建主题并在组件上订阅主题:

article.service.ts 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 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();
  }
}

Is there a best practice which I should use?是否有我应该使用的最佳实践?

We can say that Subject is a special type of Observable .我们可以说Subject是一种特殊类型的Observable

Observable : Subscribe to it to get the values. Observable :订阅它以获取值。

Subject : Same but you also have control of the values that you want to emit into it (can subscribe to it but also emit) you'll get the default value.主题:相同,但您也可以控制要发送到其中的值(可以订阅它也可以发送)您将获得默认值。

In order to understand the difference between a Subject and an Observable, you need to be aware of two distinct concepts为了理解 Subject 和 Observable 之间的区别,您需要了解两个不同的概念

  • A data producer数据生产者
  • A data consumer数据消费者

An observable, by definition is a data producer .根据定义,可观察对象是数据生产者 That is, a special kind that can produce data over time.也就是说,一种可以随时间产生数据的特殊类型。

A Subject on the other hand can act as both the – data producer and data consumer .另一方面,Subject 既可以充当数据生产者,也可以充当数据消费者

This implies two things.这意味着两件事。

  1. A subject can be subscribed to, just like an observable.一个主题可以被订阅,就像一个 observable 一样。
  2. A subject can also subscribe to other observables.一个主题还可以订阅其他可观察对象。

That being said, there is one major difference between a subject and an observable.话虽如此,主题和可观察对象之间有一个主要区别。

All subscribers to a subject share the same execution of the subject.一个主题的所有订阅者共享该主题的相同执行。 ie when a subject produces data, all of its subscribers will receive the same data.即当一个主体产生数据时,它的所有订阅者将收到相同的数据。 This behavior is different from observables, where each subscription causes an independent execution of the observable.这种行为不同于 observable,其中每个订阅都会导致 observable 的独立执行。

In your case, it may not make much difference.在你的情况下,它可能没有太大区别。 However, I can see that using subject is leading to extra processing where you first get the data via valueChanges subscription and then push it into a subject then extract data from the subject.但是,我可以看到使用主题会导致额外的处理,您首先通过valueChanges订阅获取数据,然后将其推送到主题中,然后从主题中提取数据。 This looks unnecessary.这看起来没有必要。

However, think of another component that needs the same data that you get from db valueChanges subscription.但是,请考虑另一个需要从 db valueChanges订阅获得的相同数据的组件。 In such scenarios you first collect the data from the source, push it into the subject and then multiple components which have subscribed to the same subject, they all get the data.在这种情况下,您首先从源收集数据,将其推送到主题中,然后订阅同一主题的多个组件,它们都获取数据。 Each component can then independently process the data and do their stuff.然后每个组件都可以独立处理数据并做自己的事情。

As an example let's say one component triggers some change.例如,假设一个组件触发了一些更改。 As a result of that some processing happens (say on the backend) and data comes back to the service which houses a subject.结果是发生了一些处理(比如在后端),数据返回到容纳主题的服务。 Data is now pushed to the subject and since multiple components subscribe to this subject, they all get the same data.数据现在被推送到主题,因为多个组件订阅了这个主题,它们都获得相同的数据。

As you can see this is very helpful in components communicating with each other in a loosely coupled way.如您所见,这对于组件以松散耦合方式相互通信非常有帮助。 You can create a loosely coupled, flexible, scalable system using this approach.您可以使用这种方法创建松散耦合、灵活、可扩展的系统。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM