![](/img/trans.png)
[英]What is the difference between Observable.lift and Observable.pipe in rxjs?
[英]What is the difference between Observable and a Subject in rxjs?
在流编程中有两个主要接口: Observable和Observer 。
Observable是针对消费者的,它可以被转化和订阅:
observable.map(x => ...).filter(x => ...).subscribe(x => ...)
Observer是用于提供可观察源的接口:
observer.next(newItem)
我们可以使用Observer创建新的Observable :
var observable = Observable.create(observer => {
observer.next('first');
observer.next('second');
...
});
observable.map(x => ...).filter(x => ...).subscribe(x => ...)
或者,我们可以使用同时实现Observable和Observer接口的Subject :
var source = new Subject();
source.map(x => ...).filter(x => ...).subscribe(x => ...)
source.next('first')
source.next('second')
Observable 设计为单播,Subjects 设计为多播。
如果您查看下面的示例 -每个订阅都会收到不同的值作为设计为单播开发的 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
});
如果您期望订阅的值相同,这可能会很奇怪。
我们可以使用 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());
两个订阅都获得了相同的输出值!。
可观察对象
他们很冷漠:当他们至少有一个观察者时,代码就会被执行。
创建数据副本:Observable 为每个观察者创建数据副本。
单向:Observer 不能为 observable(origin/master)赋值。
代码将为每个观察者运行。 如果是 HTTP 调用,则每个观察者都会调用它。
如果它是我们想要在所有组件之间共享的服务,它不会有最新结果所有新订阅者仍将订阅相同的 observable 并从头开始获取价值
单播意味着可以从 observable 发出值,而不是从任何其他组件发出值。
主题
它们很热:即使没有观察者,代码也会被执行并且值会被广播。
共享数据:在所有观察者之间共享相同的数据。
双向:Observer 可以为 observable(origin/master) 赋值。
如果使用 using 主题,那么您将错过在创建观察者之前广播的所有值。 所以这里来了重播主题
多播,可以将值投射到多个订阅者,并且可以同时充当订阅者和发射者
请参阅 rxjs 文档(更多信息和示例): http ://reactivex.io/rxjs/manual/overview.html#subject
什么是主题? RxJS Subject 是一种特殊类型的 Observable,它允许将值多播到许多观察者。 虽然普通的 Observable 是单播的(每个订阅的 Observer 拥有一个独立的 Observable 执行),但主题是多播的。
一个 Subject 就像一个 Observable,但可以多播给许多观察者。 主题就像 EventEmitters:它们维护着许多侦听器的注册表。
和代码,扩展Observable
Subject
: https : //github.com/ReactiveX/rxjs/blob/master/src/internal/Subject.ts#L22
/**
* @class Subject<T>
*/
export class Subject<T> extends Observable<T> implements SubscriptionLike {
//...
}
Observable 只能通知一个观察者,而 Subject 可以通知多个观察者。
我发现接受的答案有点令人困惑!
Observer不是用于提供Observable源的接口,而是用于观察Observable源的接口……从名称上看更有意义,对吗?
所以,原因是:
var observable = Observable.create(observer => {
observer.next('first');
observer.next('second');
...
});
工作 - 创建一个发出“第一个”然后“第二个”的可观察对象 - Observable.create(...)
的参数是一个订阅函数,它基本上定义了哪些Observer事件将在该Observable的直接Observer上发生。
如果你想再深入一点,重要的是要理解订阅函数在你订阅时不是直接在Observer对象上调用的,而是由一个Subscription对象中介,它可以强制执行正确的可观察规则,例如Observable永远不会在调用了observer.complete()
之后发出新值,即使您的 subscribe 函数看起来好像是这样。
参考: http : //reactivex.io/rxjs/manual/overview.html#creating-observables
一个Subject既是一个Observable又是一个观察者,再一次,它看起来就像Observer接口是将事件“馈送”给Subject 的方式。 但是,如果您意识到Subject有点像Observable并具有与 subscribe 功能等效的Observable (即,您定义观察它的事物将发生什么事件),则命名更容易理解,即使在它之后,它也位于对象上已经被创造了。 因此,您在Subject上调用Observer方法来定义观察它的事物将发生什么Observer事件! 😊(同样,涉及中间对象,以确保您只能做合法的事情序列。)
从另一个角度来看,注意到订阅一个 Observable 会重新执行 Observable 函数是好的。 例如,如果数据源是服务,这可能会导致性能问题。
如果您希望多个订阅者获得相同的值,您可能需要一个 Subject 。 为此,请确保在主题订阅数据源之前设置您的订阅。 否则,您的过程将被卡住。
更多细节在这里: https : //javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/
想象一下,如果您有一个数据流进入您的应用程序,就像在 websocket 连接中一样。 你想要一种方法来处理它。 有几个解决办法:
1.普通ajax请求:这个方案不可行,因为不适用于处理推送数据。 与其说是推,不如说是拉。
2. Promise:也不好,因为你必须触发它们并且它们只能检索一次。 也更多的是拉然后推。
所以为了取回这个数据,在过去,我们做一个长轮询。 例如,我们在这里设置了一个间隔函数来每 1 分钟检索一次该数据流。 虽然它有效,但它实际上加重了 CPU 和内存等资源的负担。
但现在有了选项 3,
3. Observable:你可以订阅并让数据流不停地进来,直到函数完成被调用。
酷吧? 但是还有另一个问题。 如果您只想在应用程序中的某处观察一次传入数据,该怎么办? 但是您希望在数据到达时在您的应用程序周围同时使用该数据。 那是您何时何地使用主题。 您将 subject.subscribe() 放在您希望在整个应用程序中使用的地方。 当数据到达时,有subject.subscribe() 的地方会同时处理它们。 但是观察者必须像这样订阅主题作为其参数。
观察者.订阅(主题)。
示例应用程序是当您想要构建通知警报时。
您不能对同一个 observable 进行多个订阅,因为很有可能每个订阅者都会收到不同的输入数据。 但是对于主题,所有通过主题 subscribe() 的操作都将检索相同的数据。
另一个类比是通过杂志订阅。 每个订阅者都会收到带有他们名字的杂志。 所以,不同的订阅 = 不同的接收者姓名。(Normal Observable)但是当你与你的朋友分享时,你所有的朋友都会收到同样的杂志,上面只有你的名字。(Normal Observable with Subject)
这家伙用代码示例很好地解释了它。 您可以在https://javascript.tutorialhorizon.com/2017/03/23/rxjs-subject-vs-observable/查看
希望这个答案有帮助。
Observable :只有 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);
});
Subject :这里的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);
简要地,
主题:您可以发送到它并从中接收。
观察到的:你可以从它只能接收。
换句话说,在主题中你可以订阅它,你可以使用它随时随地在代码中广播给其他订阅者。
同时,在观察到你只能订阅(它初始化之后,你不能用它来广播数据)。 唯一可以从 observable 广播数据的地方是它的构造函数内部。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.