乐闻世界logo
搜索文章和话题

What is the difference between Observable and a Subject in rxjs?

9 个月前提问
5 个月前修改
浏览次数114

9个答案

1
2
3
4
5
6
7
8
9

当然,我很乐意回答这个问题。

在RxJS中,ObservableSubject都是可观察序列的基础构建块,但它们在功能和用法上有一些关键的区别:

Observable

  1. 基本概念Observable是RxJS提供的一种数据类型,它表示一个可随时间推送值的异步数据流。你可以订阅(subscribe)一个Observable,然后在值到来的时候通过提供的回调函数进行处理。

  2. 单向数据流Observable是单向数据流的,意味着它们可以发射(emit)数据、完成(complete)或者发出错误(error),但是外部是无法直接对Observable发射的数据流进行控制的。

  3. 冷Observable:默认情况下,Observable是冷的(cold),这意味着每一个订阅者都会得到一个独立的数据流。这就是说,Observable在每次有新的订阅者订阅时,都会重新启动数据流。因此,每个订阅者都能看到完整的数据序列。

    例子:如果你创建一个基于HTTP请求的Observable,每次调用.subscribe()时,都会发起一个新的HTTP请求。

Subject

  1. 基本概念Subject继承自Observable,因此它既是一个Observable也是一个Observer。这意味着Subject不仅可以像Observable那样发射值,还可以订阅其他Observable。

  2. 双向数据流:与Observable不同,Subject可以是多播的(multicast),它可以同时作为数据源和消费者。你可以手动调用.next()方法来向所有的订阅者推送新的值,从而允许外部对Subject发射的数据流进行控制。

  3. 热Observable:Subject是热的(hot),这意味着它会共享单个数据流给所有订阅者。不会像冷Observable那样对每个订阅者重新发射数据,而是当一个新的值被推送时,所有的订阅者都能收到这个新值。

    例子:如果你有一个WebSocket连接的Subject,那么无论有多少订阅者,数据都是通过同一个WebSocket连接发送和接收的。

举例

为了更清楚地理解两者的差异,让我给出一个例子:

假设我们正在构建一个实时股票价格更新系统,对于股票价格的更新,我们可能会使用Subject,因为我们希望所有的订阅者看到同样的价格变动,而不需要为每个订阅者重新获取数据。

而对于用户的个人交易请求,每个请求可能都是独立的,我们可能会为每个请求创建一个新的Observable,以确保每次操作都是独立的而且互不影响。

总结来说,Observable适用于单向、独立的数据流,而Subject更适合那些需要多播或由外部主动推送数据的场景。

2024年6月29日 12:07 回复

在流编程中有两个主要接口:ObservableObserver

Observable是针对消费者的,它可以被转换和订阅:

shell
observable.map(x => ...).filter(x => ...).subscribe(x => ...)

观察者是用于提供可观察源的接口:

shell
observer.next(newItem)

我们可以使用Observer创建新的****Observable

shell
var observable = Observable.create(observer => { observer.next('first'); observer.next('second'); ... }); observable.map(x => ...).filter(x => ...).subscribe(x => ...)

或者,我们可以使用一个同时实现ObservableObserver接口的****主题

shell
var source = new Subject(); source.map(x => ...).filter(x => ...).subscribe(x => ...) source.next('first') source.next('second')
2024年6月29日 12:07 回复

Observables 按设计是单播的,Subjects 按设计是多播的。

如果您查看下面的示例,您会发现每个订阅都会收到不同的值,因为可观察量按设计开发为单播。

shell
import {Observable} from 'rxjs'; let obs = new Observable<any>(observer=>{ observer.next(Math.random()); }) obs.subscribe(res=>{ console.log('subscription a :', res); //subscription a :0.2859800202682865 }); obs.subscribe(res=>{ console.log('subscription b :', res); //subscription b :0.694302021731573 });

如果您希望两个订阅具有相同的值,这可能会很奇怪。

我们可以使用主题来解决这个问题。**主题与事件发射器类似,它不会为每个订阅调用。**考虑下面的例子。

shell
import {Subject} from 'rxjs'; let obs = new Subject(); obs.subscribe(res=>{ console.log('subscription a :', res); // subscription a : 0.91767565496093 }); obs.subscribe(res=>{ console.log('subscription b :', res);// subscription b : 0.91767565496093 }); obs.next(Math.random());

两个订阅都获得相同的输出值!

2024年6月29日 12:07 回复

观测值

  1. 它们很冷:当它们至少有一个观察者时,代码就会被执行。

  2. 创建数据副本:Observable 为每个观察者创建数据副本。

  3. 单向:观察者不能给 observable(origin/master) 赋值。

  4. 该代码将为每个观察者运行。如果是 HTTP 调用,则每个观察者都会调用它。

  5. 如果它是我们想要在所有组件之间共享的服务,它不会有最新结果,所有新订阅者仍然会订阅相同的可观察对象并从头开始获取价值

  6. 单播意味着可以从 observable 发出值,而不是从任何其他组件发出值。

主题

  1. 它们很热门:即使没有观察者,代码也会被执行并且值也会被广播。

  2. 共享数据:相同的数据在所有观察者之间共享。

  3. 双向:观察者可以为 observable(origin/master)赋值。

  4. 如果使用主题,那么您会错过创建观察者之前广播的所有值。那么重播主题来了

  5. 多播,可以将值投射给多个订阅者,并且可以充当订阅者和发射者

2024年6月29日 12:07 回复

我发现接受的答案有点令人困惑!

观察者_不是用于提供_Observable源的接口,而是用于_观察_Observable源的接口……从名称上看 ,这更有意义,对吧?

那么,原因是:

shell
var observable = Observable.create(observer => { observer.next('first'); observer.next('second'); ... });

工作原理 - 创建一个发出“第一个”然后发出“第二个”的 observable - 的参数是Observable.create(...)一个_subscribe 函数_,它基本上定义了哪些Observer事件将在该Observable的直接观察者上发生。

如果您想再深入一点,重要的是要了解订阅函数在订阅时_不会直接在_观察者对象上调用,而是由订阅对象介导,该对象可以强制执行正确的可观察规则,例如Observable在被调用后永远不会发出新值,即使你的 subscribe 函数看起来好像会发出新值**。**observer.complete()

参考: http: //reactivex.io/rxjs/manual/overview.html#creating-observables

一个Subject既是一个Observable又是一个Observer,它_看起来_就像Observer接口是向****Subject “提供”事件的方式。但是,如果您意识到一个Subject有点像一个Observable,具有相当于订阅功能的功能(即您定义观察它的事物将发生什么事件),那么它的命名就更容易理解了,它就位于对象上,即使在它之后已经被创造了。因此,您可以在主题上调用****观察者方法来定义观察它的事物将发生什么**观察者事件!**😊(同样,涉及中间对象,以确保您只能执行合法的事情序列。)

参考:http: //reactivex.io/rxjs/manual/overview.html#subject

2024年6月29日 12:07 回复

请参阅 rxjs 文档(那里有更多信息和示例): http://reactivex.io/rxjs/manual/overview.html#subject

什么是主题?RxJS主题是一种特殊类型的Observable,它允许将值多播到许多观察者。普通 Observable 是单播的(每个订阅的观察者都拥有 Observable 的独立执行),而主题是多播的。

一个Subject就像一个Observable,但可以多播到许多观察者。主题就像 EventEmitters:它们维护许多侦听器的注册表。

和代码,Subject扩展Observablehttps://github.com/ReactiveX/rxjs/blob/master/src/internal/Subject.ts#L22

shell
/** * @class Subject<T> */ export class Subject<T> extends Observable<T> implements SubscriptionLike { //... }
2024年6月29日 12:07 回复

rxjs 中的 Observable 和Subject 有什么区别?,ObservableSubject 都是 RxJS 库中的重要概念,它们用于处理异步事件和基于推送模型的数据流,但它们之间有一些关键区别:

Observable

  • 基础概念: Observable 是 RxJS 中的基础类。它代表一个可观察的序列,可以发出三种类型的事件:值、错误和完成通知。
  • 单播性质: Observable 是单播的,这意味着对于每个订阅者,Observable 都会独立执行。如果你有多个订阅者,每个订阅者都会观察到独立的事件序列。
  • 惰性运行: Observable 在默认情况下是惰性的,也就是说,它只有在有订阅者时才开始执行。这与函数调用类似,只有当你调用它时,它才会运行。
  • 操作符: Observable 可以使用各种 RxJS 提供的操作符进行转换、合并、过滤等操作。

Subject

  • 特殊的 Observable: Subject 是一种特殊类型的 Observable,它允许将值多播给多个观察者。这意味着当一个 Subject 发出一个事件时,所有的订阅者都会接收到相同的事件。
  • 观察者身份: Subject 也实现了 Observer 接口,这使它可以作为数据源,你可以明确地调用 next(value)error(e)complete() 方法来发出事件,这是普通 Observable 无法做到的。
  • 热数据流: 由于 Subject 是多播的,它通常代表“热”数据流。一旦值被发出,不论是否存在订阅者,该值可能会丢失。如果后来有新的订阅者,它们可能会错过之前发出的事件。
  • 变种: Subject 有几个变种,包括 BehaviorSubjectReplaySubjectAsyncSubject,它们具有不同的行为特性,比如能够缓存值。

对比总结

  • 多播与单播: Observable 是单播,每个订阅者都有独立的执行上下文;而 Subject 是多播,多个观察者共享同一事件流。
  • 主动与被动: Subject 可以主动发出事件,而 Observable 是被动的,它通过操作符或者创建函数来发出事件。
  • 热与冷: Observable 通常用于表示冷数据流,而 Subject 表示热数据流。

在实际应用中,选择使用 Observable 还是 Subject 取决于你的特定需求,比如是否需要多播、是否需要主动控制事件的发出等。

2024年6月29日 12:07 回复

ObservableSubject 都是 RxJS 库中的重要概念,它们用于处理异步事件和基于推送模型的数据流,但它们之间有一些关键区别:

Observable

  • 基础概念: Observable 是 RxJS 中的基础类。它代表一个可观察的序列,可以发出三种类型的事件:值、错误和完成通知。
  • 单播性质: Observable 是单播的,这意味着对于每个订阅者,Observable 都会独立执行。如果你有多个订阅者,每个订阅者都会观察到独立的事件序列。
  • 惰性运行: Observable 在默认情况下是惰性的,也就是说,它只有在有订阅者时才开始执行。这与函数调用类似,只有当你调用它时,它才会运行。
  • 操作符: Observable 可以使用各种 RxJS 提供的操作符进行转换、合并、过滤等操作。

Subject

  • 特殊的 Observable: Subject 是一种特殊类型的 Observable,它允许将值多播给多个观察者。这意味着当一个 Subject 发出一个事件时,所有的订阅者都会接收到相同的事件。
  • 观察者身份: Subject 也实现了 Observer 接口,这使它可以作为数据源,你可以明确地调用 next(value)error(e)complete() 方法来发出事件,这是普通 Observable 无法做到的。
  • 热数据流: 由于 Subject 是多播的,它通常代表“热”数据流。一旦值被发出,不论是否存在订阅者,该值可能会丢失。如果后来有新的订阅者,它们可能会错过之前发出的事件。
  • 变种: Subject 有几个变种,包括 BehaviorSubjectReplaySubjectAsyncSubject,它们具有不同的行为特性,比如能够缓存值。

对比总结

  • 多播与单播: Observable 是单播,每个订阅者都有独立的执行上下文;而 Subject 是多播,多个观察者共享同一事件流。
  • 主动与被动: Subject 可以主动发出事件,而 Observable 是被动的,它通过操作符或者创建函数来发出事件。
  • 热与冷: Observable 通常用于表示冷数据流,而 Subject 表示热数据流。

在实际应用中,选择使用 Observable 还是 Subject 取决于你的特定需求,比如是否需要多播、是否需要主动控制事件的发出等。

2024年6月29日 12:07 回复

在RxJS中,ObservableSubject都是可观察序列的基础构建块,但它们在功能和用法上有一些关键的区别:

Observable

  1. 基本概念Observable是RxJS提供的一种数据类型,它表示一个可随时间推送值的异步数据流。你可以订阅(subscribe)一个Observable,然后在值到来的时候通过提供的回调函数进行处理。

  2. 单向数据流Observable是单向数据流的,意味着它们可以发射(emit)数据、完成(complete)或者发出错误(error),但是外部是无法直接对Observable发射的数据流进行控制的。

  3. 冷Observable:默认情况下,Observable是冷的(cold),这意味着每一个订阅者都会得到一个独立的数据流。这就是说,Observable在每次有新的订阅者订阅时,都会重新启动数据流。因此,每个订阅者都能看到完整的数据序列。

    例子:如果你创建一个基于HTTP请求的Observable,每次调用 .subscribe()时,都会发起一个新的HTTP请求。

Subject

  1. 基本概念Subject继承自Observable,因此它既是一个Observable也是一个Observer。这意味着Subject不仅可以像Observable那样发射值,还可以订阅其他Observable。

  2. 双向数据流:与Observable不同,Subject可以是多播的(multicast),它可以同时作为数据源和消费者。你可以手动调用 .next()方法来向所有的订阅者推送新的值,从而允许外部对Subject发射的数据流进行控制。

  3. 热Observable:Subject是热的(hot),这意味着它会共享单个数据流给所有订阅者。不会像冷Observable那样对每个订阅者重新发射数据,而是当一个新的值被推送时,所有的订阅者都能收到这个新值。

    例子:如果你有一个WebSocket连接的Subject,那么无论有多少订阅者,数据都是通过同一个WebSocket连接发送和接收的。

举例

为了更清楚地理解两者的差异,让我给出一个例子:

假设我们正在构建一个实时股票价格更新系统,对于股票价格的更新,我们可能会使用Subject,因为我们希望所有的订阅者看到同样的价格变动,而不需要为每个订阅者重新获取数据。

而对于用户的个人交易请求,每个请求可能都是独立的,我们可能会为每个请求创建一个新的Observable,以确保每次操作都是独立的而且互不影响。

总结来说,Observable适用于单向、独立的数据流,而 Subject更适合那些需要多播或由外部主动推送数据的场景。

2024年6月29日 12:07 回复

你的答案