我正在研究Angular RxJs模式,我不明白行为主体和可观察对象之间的区别。
根据我的理解,BehaviorSubject是一个可以随时间变化的值(可以订阅,订阅者可以接收更新的结果)。这似乎与可观察对象的目的完全相同。
什么时候使用可观察对象和行为主体?使用一个行为主体比使用一个可观察对象有好处吗?反之亦然?
我正在研究Angular RxJs模式,我不明白行为主体和可观察对象之间的区别。
根据我的理解,BehaviorSubject是一个可以随时间变化的值(可以订阅,订阅者可以接收更新的结果)。这似乎与可观察对象的目的完全相同。
什么时候使用可观察对象和行为主体?使用一个行为主体比使用一个可观察对象有好处吗?反之亦然?
当前回答
BehaviorSubject
BehaviorSubject构建在与我们的ReplaySubject相同的功能之上,比如,hot,并重放先前的值。
BehaviorSubject又增加了一个功能,您可以给BehaviorSubject一个初始值。让我们继续,看看这段代码
import { ReplaySubject } from 'rxjs';
const behaviorSubject = new BehaviorSubject(
'hello initial value from BehaviorSubject'
);
behaviorSubject.subscribe(v => console.log(v));
behaviorSubject.next('hello again from BehaviorSubject');
观察
首先,我们来看看创建常规Observable的最小API。有几种方法可以创建Observable。创建Observable的方法是实例化类。其他操作符可以简化这个步骤,但我们希望将实例化步骤与不同的Observable类型进行比较
import { Observable } from 'rxjs';
const observable = new Observable(observer => {
setTimeout(() => observer.next('hello from Observable!'), 1000);
});
observable.subscribe(v => console.log(v));
其他回答
我在例子中没有看到的一件事是,当你通过asObservable将BehaviorSubject转换为Observable时,它继承了订阅时返回最后一个值的行为。
这是很棘手的一点,因为库通常会将字段作为可观察对象公开(例如,在Angular2中ActivatedRoute中的参数),但可能会在幕后使用Subject或BehaviorSubject。他们使用什么会影响订阅行为。
请看这里http://jsbin.com/ziquxapubo/edit?html,js,console
let A = new Rx.Subject();
let B = new Rx.BehaviorSubject(0);
A.next(1);
B.next(1);
A.asObservable().subscribe(n => console.log('A', n));
B.asObservable().subscribe(n => console.log('B', n));
A.next(2);
B.next(2);
app.component.ts
behaviourService.setName("behaviour");
behaviour.service.ts
private name = new BehaviorSubject("");
getName = this.name.asObservable();
constructor() {}
setName(data) {
this.name.next(data);
}
custom.component.ts
behaviourService.subscribe(response=>{
console.log(response); //output: behaviour
});
在rxjs中,Subject本质上是一个观察者和可观察对象。观察者是我们放入值的对象,可观察对象是我们可以观察值的对象。
Subject is Hot by default. Observables by default are cold. That means they are not going to emit any values until someone subscribes to it. The instant we create a subject, we can emit a value from it and that value will be emitted even if nobody is subscribed to it yet. Subject is multicast by default. Observable by default are unicast and that means that for every different observer that we have, we have to subscibe to an observable, if that observable emits a value that value is going to flow through all the different operators inside of our pipe once for each subscriber. Multicast means all of other operators will run one time for every value, regardless of the number of observers we have. GOTCHA= thE SUBJECT is multicast but if you chain on a pipe statement to it, that is going to return a new observable that is cold and unicast.
行为主体与主体相同,但也有初始的“种子”值。新订阅用户立即获得最新的值。如果有人订阅了行为主体,它会立即接收到最近的值。所以行为主体总有一些价值可以分给订阅者。
关于行为主体最有用的事情是当我们开始发出网络请求时。想象一下,我们将一些管道连接到一个行为主题上,在一个管道函数或管道操作符中,我们最终发出一个网络请求并获取一些数据。你最终可能会想让其他东西订阅那个可观察对象,并立即获得已经获取的数据。使用行为主体,我们可以很容易地实现这种行为。
BehaviorSubject
BehaviorSubject构建在与我们的ReplaySubject相同的功能之上,比如,hot,并重放先前的值。
BehaviorSubject又增加了一个功能,您可以给BehaviorSubject一个初始值。让我们继续,看看这段代码
import { ReplaySubject } from 'rxjs';
const behaviorSubject = new BehaviorSubject(
'hello initial value from BehaviorSubject'
);
behaviorSubject.subscribe(v => console.log(v));
behaviorSubject.next('hello again from BehaviorSubject');
观察
首先,我们来看看创建常规Observable的最小API。有几种方法可以创建Observable。创建Observable的方法是实例化类。其他操作符可以简化这个步骤,但我们希望将实例化步骤与不同的Observable类型进行比较
import { Observable } from 'rxjs';
const observable = new Observable(observer => {
setTimeout(() => observer.next('hello from Observable!'), 1000);
});
observable.subscribe(v => console.log(v));
观察:每个观察者的结果不同
一个非常非常重要的区别。因为Observable只是一个函数,它没有任何状态,所以对于每个新的Observer,它都会一次又一次地执行可观察对象的创建代码。结果是:
为每个观察者运行代码 . 如果它是一个HTTP调用,它会被每个观察者调用
这会导致主要的错误和低效率
BehaviorSubject(或Subject)存储观察者细节,只运行一次代码,并将结果提供给所有观察者。
Ex:
JSBin: http://jsbin.com/qowulet/edit?js,console
// --- Observable --- let randomNumGenerator1 = Rx.Observable.create(observer => { observer.next(Math.random()); }); let observer1 = randomNumGenerator1 .subscribe(num => console.log('observer 1: '+ num)); let observer2 = randomNumGenerator1 .subscribe(num => console.log('observer 2: '+ num)); // ------ BehaviorSubject/ Subject let randomNumGenerator2 = new Rx.BehaviorSubject(0); randomNumGenerator2.next(Math.random()); let observer1Subject = randomNumGenerator2 .subscribe(num=> console.log('observer subject 1: '+ num)); let observer2Subject = randomNumGenerator2 .subscribe(num=> console.log('observer subject 2: '+ num)); <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.3/Rx.min.js"></script>
输出:
"observer 1: 0.7184075243594013"
"observer 2: 0.41271850211336103"
"observer subject 1: 0.8034263165479893"
"observer subject 2: 0.8034263165479893"
观察如何使用Observable。create为每个观察者创建了不同的输出,但BehaviorSubject为所有观察者提供了相同的输出。这很重要。
总结了其他差异。
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Observable ┃ BehaviorSubject/Subject ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Is just a function, no state ┃ Has state. Stores data in memory ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Code run for each observer ┃ Same code run ┃
┃ ┃ only once for all observers ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Creates only Observable ┃Can create and also listen Observable┃
┃ ( data producer alone ) ┃ ( data producer and consumer ) ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Usage: Simple Observable with only ┃ Usage: ┃
┃ one Obeserver. ┃ * Store data and modify frequently ┃
┃ ┃ * Multiple observers listen to data ┃
┃ ┃ * Proxy between Observable and ┃
┃ ┃ Observer ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛