rxjs中Observable和Subject之间有什么区别?

时间:2017-11-28 17:50:13

标签: javascript angular rxjs reactive-programming

我正在浏览这个blog并阅读有关Observables的内容,我无法弄清楚Observable与主题之间的区别

9 个答案:

答案 0 :(得分:39)

可观察对象是按设计单播的,而主题是按设计组播的。

如果您看下面的示例-每个订阅都将不同的值接收为可观察的观测值,这些观测值是根据设计单播开发的。

import {Observable} from 'rxjs';

let obs = Observable.create(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
});

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

我们可以使用“主题”解决此问题。主题类似于事件发射器,并且不会为每个订阅调用。考虑下面的示例。

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());

两个订阅都具有相同的输出值!。

答案 1 :(得分:16)

在流编程中有两个主要界面:可观察观察者

可观察适用于消费者,可以进行转换和订阅:

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

观察者是用于提供可观察来源的界面:

observer.next(newItem)

我们可以使用观察者创建新的可观察

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

或者,我们可以使用主题来实现 Observable Observer 接口:

var source = new Subject();
source.map(x => ...).filter(x => ...).subscribe(x => ...)
source.next('first')
source.next('second')

答案 2 :(得分:9)

可观察物

  1. 它们很冷:只有至少一个观察者时,代码才能执行。

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

  3. 单向:观察者无法将值分配给observable(源/主)。

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

  5. 如果我们要在所有组件之间共享其服务,它将不会有最新的结果,所有新订户仍将订阅相同的可观察指标并从头开始获得价值

  6. 单播方式可以从可观察到的值发出值,而不能从任何其他组件发出。

主题

  1. 它们很热:即使没有观察者,代码也会被执行,价值也会得到传播。

  2. 共享数据:所有观察者共享同一数据。

  3. 双向:观察者可以将值分配给observable(来源/主对象)。

  4. 如果正在使用主题,则您会错过创建观察者之前广播的所有值。所以这里是重播主题

  5. 多播,可以将值转换为多个订阅者,并且既可以充当订阅者又可以充当发射者

答案 3 :(得分:5)

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

  

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

     

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

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

/**
 * @class Subject<T>
 */
export class Subject<T> extends Observable<T> implements SubscriptionLike {
//...
}

答案 4 :(得分:5)

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

观察者 不是用于提供可观察源的界面,它是观察的界面可观察的来源...从名称上讲更有意义,对吧?

所以,原因如下:

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

有效-创建一个发出“第一”然后“第二”的可观察对象-是Observable.create(...)的参数是订阅函数,它基本上定义了哪个观察者事件将在该可观察的直接观察者上发生。

如果您想再进一步一点,请务必理解,在订阅时,不是直接在 Observer 对象上调用了订阅函数 ,而是由 Subscription 对象执行,该对象可以实施正确的可观察规则,例如这样,即使您的订阅函数看起来像 Observable 也不会在调用observer.complete()之后发出新值。

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

主题既是可观察,又是观察者,它又看起来,就像观察者界面是将事件“馈送”到主题的方式。但是,如果您意识到 Subject 有点像 Observable 且具有订阅功能的等效功能(即定义发生什么事件的位置),则更容易理解其命名。观察它的东西)就坐在对象上,即使它已经创建。因此,您可以在主题上调用 Observer 方法,以定义在观察它的事物上将发生什么 Observer 事件! ?(同样,涉及到中间对象,以确保您只能做合法的事情序列。)

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

答案 5 :(得分:3)

从另一个角度来看,很高兴注意到 Observable的订阅重新执行了Observable函数。如果数据源例如是服务,则可能导致性能问题。

如果您希望多个订阅者获得相同的价值,则可能需要一个主题。 为此,请确保您的订阅设置为之前,主题已订阅数据源。否则,您的进程将被卡住。

此处有更多详细信息:https://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/

答案 6 :(得分:1)

Observable can inform only one observer, while Subject can inform multiple observers.

答案 7 :(得分:1)

可观察: 只有 Observable 知道如何以及何时在 observable 上触发事件。即 next() 方法只能在实例化的构造函数中调用。此外,每次订阅时,都会创建一个单独的观察者并仅在构造函数内部使用特定观察者调用 next() 方法,在以下示例中,subscriber 本身就是观察者,并且在实例化的构造函数执行时订阅它. 例如:

import { Observable } from 'rxjs';

const observable = new Observable(subscriber => {
  subscriber.next(1);
  subscriber.next(2);
  setTimeout(() => {
    subscriber.next(3);        
  }, 1000);
});

主题: 这里的 next() 方法可以被构造函数之外的任何地方的主体使用。此外,在订阅之前调用 next() 方法时,将错过特定事件。因此 next() 方法只能在订阅后调用。 例如:

import { Subject } from 'rxjs';
 
const subject = new Subject<number>();
 

subject.next(1); // this is missed
subject.subscribe({
  next: (v) => console.log(`observerA: ${v}`)
});
subject.subscribe({
  next: (v) => console.log(`observerB: ${v}`)
});     
subject.next(2);

答案 8 :(得分:0)

想象一下,如果像websocket连接中那样有数据流进入应用程序。您想要一种处理它的方法。有一些解决方案:

1。正常的ajax请求:     该解决方案不可行,因为它是     不适用于处理推送数据。然后更多的是拉     推。

2。承诺:     同样不好,因为您必须触发它们,     他们只能检索一次。还有更多的拉动然后是推动。

因此,为了检索此数据,在过去,我们进行了长时间轮询。例如,我们在此处设置间隔函数以每1分钟检索一次该数据流。尽管可以,但实际上却负担着CPU和内存等资源。

但是现在有了选项3,

3。可观察:您可以订阅并让数据流进入     直到调用完成函数为止。

很酷吧?但是,这还有另一个问题。如果您只想在应用程序中某处仅观察一次传入数据,该怎么办。但是,您希望在数据到达时在应用程序中同时使用这些数据。那就是您何时何地使用Subject。 您可以将subject.subscribe()放置在整个应用程序中要使用的位置。当数据到达时,有subject.subscribe()的地方将同时处理它们。但是观察者必须这样接受主题作为论点。

  

observer.subscribe(主题)。

示例应用程序是您要构建通知警报的时候。

您不能同时拥有多个可观察的订阅,因为每个订阅者都有可能收到不同的输入数据。但是有了主题,所有通过主题的subscribe()都将检索相同的数据。

另一个比喻是通过杂志订阅。每个订阅者都会收到杂志,上面有他们的名字。因此,不同的订阅=不同的接收者名称。(可正常观察) 但是当您与朋友分享时,所有朋友都会收到同一本杂志,上面只有您的名字。(主题可正常观看)

这个人用代码示例很好地解释了这一点。您可以在https://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/

签出

希望这个答案会有所帮助。