javascript rxjs 中的 Observable 和 Subject 有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47537934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 07:27:05  来源:igfitidea点击:

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

javascriptangularrxjsreactive-programming

提问by Lijin Durairaj

i was going through this blogand to read about Observables and i couldnt figure out the difference between the Observable and a Subject

我正在浏览这个博客并阅读有关 Observables 的内容,但我无法弄清楚 Observable 和 Subject 之间的区别

回答by ZahiC

In stream programming there are two main interfaces: Observableand Observer.

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

Observableis for the consumer, it can be transformed and subscribed:

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

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

Observeris the interface which is used to feed an observable source:

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

observer.next(newItem)

We can create new Observablewith an Observer:

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

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

Or, we can use a Subjectwhich implements both the Observableand the Observerinterfaces:

或者,我们可以使用一个主题,它实现两个可观察观察接口:

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

回答by jaideep_johny

Observables

可观察对象

  1. They are cold: Code gets executed when they have at least a single observer.

  2. Creates copy of data: Observable creates copy of data for each observer.

  3. Uni-directional: Observer can not assign value to observable(origin/master).

  4. The code will run for each observer . If its a HTTP call, it gets called for each observer.

  5. if its a service we want to share among all the components, it wont have latest result all new subscribers will still subscribe to same observable and get value from scratch

  6. Unicast means can emit values from the observable not from any other component.

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

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

  3. 单向:Observer 不能为 observable(origin/master)赋值。

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

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

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

Subject

主题

  1. They are hot: code gets executed and value gets broadcast even if there is no observer.

  2. Shares data: Same data get shared between all observers.

  3. bi-directional: Observer can assign value to observable(origin/master).

  4. If are using using subject then you miss all the values that are broadcast before creation of observer. So here comes Replay Subject

  5. multicast, can cast values to multiple subscribers and can act as both subscribers and emmitter

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

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

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

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

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

回答by John Smith

See rxjs document (more information and examples there): http://reactivex.io/rxjs/manual/overview.html#subject

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

What is a Subject? An RxJS Subject is a special type of Observable that allows values to be multicasted to many Observers. While plain Observables are unicast (each subscribed Observer owns an independent execution of the Observable), Subjects are multicast.

A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners.

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

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

and code, Subjectextending Observable: https://github.com/ReactiveX/rxjs/blob/master/src/internal/Subject.ts#L22

和代码,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 {
//...
}

回答by Mehul Jain

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

Observable 只能通知一个观察者,而 Subject 可以通知多个观察者。

回答by jaibalaji

Observables are unicast by design and Subjects are multicast by design.

Observables 设计为单播,Subjects 设计为多播。

if you look at the below example - each subscription recieves the diffrent values as observables developed as unicast by design.

如果您查看下面的示例 - 每个订阅都会收到不同的值作为设计为单播开发的 observable。

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

this could be weird if you are expecting the same values on both the subscription.

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

we can overcome this issue using Subjects. Subjects is similar to event-emitter and it does not invoke for each subscription. consider the below example.

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

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

both the subscription are got the same output value!.

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

回答by VincentPerrin.com

From another perspective, it is good to note that the subscription to an Observable re-execute the Observable function. This can lead performance issue if the data source is a service for instance.

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

If you want several subscribers to get the same value, you may need a Subject. For this, make sure that your subscription is set beforethe Subject subscribed to the data source. Otherwise, your process would be stuck.

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

More details here: https://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/

更多细节在这里:https: //javascript.tutorialhorizo​​n.com/2017/03/23/rxjs-subject-vs-observable/

回答by Apit John Ismail

Imagine if you have a stream of data coming into your application like in a websocket connection. You want a way to handle it. There is a few solution:

想象一下,如果您有一个数据流进入您的应用程序,就像在 websocket 连接中一样。你想要一种方法来处理它。有几个解决办法:

1. normal ajax request:This solution is not viable because it is not applicable to process push data. It is more of a pull then a push.

1.普通ajax请求:这个方案不可行,因为不适用于处理推送数据。与其说是推,不如说是拉。

2. Promise:Also not good because you have to trigger them and they can only retrieve once. Also more of a pull then a push.

2. Promise:也不好,因为你必须触发它们并且它们只能检索一次。也更多的是拉然后推。

So in order to retrieve this data, in the old time, we do a long-polling. Which is where we set an interval function to retrieve that stream of data every 1 minute for an example. Though it works, it actually burdening resources like CPU and memory.

所以为了取回这些数据,在过去,我们做一个长轮询。例如,我们在这里设置了一个间隔函数来每 1 分钟检索一次该数据流。虽然它有效,但它实际上加重了 CPU 和内存等资源的负担。

But now with option no 3,

但是现在有了选项 3,

3. Observable:You can subscribe and let the stream of data to come in non-stop until the function complete has been called.

3. Observable:你可以订阅并让数据流不停地进来,直到函数完成被调用。

Cool right ? But then there is another problem. What if you want to observe incoming data only once somewhere in your application. But you want to use that data simultaneously around your application when the data arrived. That is when and where you use Subject. You place subject.subscribe() at places you want to use throughout your application. When the data arrived, places where there is subject.subscribe() will process them simultaneously. But the observer must subscribe with the subject as its argument like this.

酷吧?但是还有另一个问题。如果您只想在应用程序中的某处观察一次传入数据,该怎么办?但是您希望在数据到达时在您的应用程序周围同时使用该数据。那是您使用主题的时间和地点。您将 subject.subscribe() 放在您希望在整个应用程序中使用的地方。当数据到达时,有subject.subscribe() 的地方会同时处理它们。但是观察者必须像这样订阅主题作为其参数。

observer.subscribe(subject).

观察者.订阅(主题)。

Example application is when you want to build a notification alert.

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

You cannot have multiple subscription of the same observable because chances are, each subscribers will received different input data. But with subject, all that subscribe() through subject will be retrieving the same data.

您不能对同一个 observable 进行多个订阅,因为很有可能每个订阅者都会收到不同的输入数据。但是对于主题,所有通过主题 subscribe() 的操作都将检索相同的数据。

Another analogy is through magazine subscription. Each subscribers will received the magazine with their name on it. So, different subscription = different receiver name.(Normal Observable) But when you share with your friends, all of your friend would receive the same magazine with only your name on it.(Normal Observable with Subject)

另一个类比是通过杂志订阅。每个订阅者都会收到带有他们名字的杂志。所以,不同的订阅 = 不同的接收者姓名。(Normal Observable)但是当你与你的朋友分享时,你所有的朋友都会收到同样的杂志,上面只有你的名字。(Normal Observable with Subject)

This guy explain it very well with code example. You can check it out at https://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/

这家伙用代码示例很好地解释了它。您可以在https://javascript.tutorialhorizo​​n.com/2017/03/23/rxjs-subject-vs-observable/查看

Hopefully this answer helps.

希望这个答案有帮助。

回答by MikeBeaton

I found the accepted answer slightly confusing!

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

An Observerisn'tthe interface for feeding an Observablesource, it's the interface for for observingan Observablesource... which makes more sense from the name, right?

一个观察员用于喂养的接口可观察源,它的接口为观察可观察源...这使得从名字更有意义吧?

So, the reason that:

所以,原因是:

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

works - creating an observable which emits 'first' then 'second' - is that the argument to Observable.create(...)is a subscribe function, it basically defines which Observerevents will happen on a direct Observerof that Observable.

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

If you want to go into it a little bit further again, it's important to understand that the subscribe function isn'tdirectly called on the Observerobject when you subscribe, instead it's mediated by a Subscriptionobject which can enforce correct observable rules, e.g. that an Observablewill never emit a new value after observer.complete()has been called, even if your subscribe function looks as if it would.

如果你想再深入一点,重要的是要理解订阅函数在你订阅时不是直接在Observer对象上调用的,而是由一个Subscription对象中介,它可以强制执行正确的可观察规则,例如一个可观察绝不会发出一个新的值之后observer.complete()被调用,即使你的订阅功能,看起来好像会。

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

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

A Subjectis both an Observableand an Observerand once again it looksjust like the Observerinterface is the way to 'feed' events to the Subject. But it's easier to understand the naming if you realise that a Subjectis a bit like an Observablewith the equivalent of the subscribe function (i.e. where you define what events will happen to things observing it) sitting there right on the object, even after it has been created. So, you call Observermethods on the Subjectto define what Observerevents will happen on things observing it! (And again, there are intermediate objects involved, to make sure that you can only do legal sequences of things.)

一个Subject既是一个Observable又是一个观察者,再一次,它看起来就像Observer接口是将事件“馈送”给Subject 的方式。但是,如果您意识到Subject有点像Observable并具有与 subscribe 功能等效的Observable(即您定义观察它的事物将发生什么事件的地方),则它更容易理解命名坐在对象上,即使在它之后已经被创造了。所以,你在Subject上调用Observer方法来定义什么Observer事件会发生在观察它的事物上!(同样,涉及中间对象,以确保您只能做合法的事情序列。)

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

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