我正在研究Angular RxJs模式,我不明白行为主体和可观察对象之间的区别。
根据我的理解,BehaviorSubject是一个可以随时间变化的值(可以订阅,订阅者可以接收更新的结果)。这似乎与可观察对象的目的完全相同。
什么时候使用可观察对象和行为主体?使用一个行为主体比使用一个可观察对象有好处吗?反之亦然?
我正在研究Angular RxJs模式,我不明白行为主体和可观察对象之间的区别。
根据我的理解,BehaviorSubject是一个可以随时间变化的值(可以订阅,订阅者可以接收更新的结果)。这似乎与可观察对象的目的完全相同。
什么时候使用可观察对象和行为主体?使用一个行为主体比使用一个可观察对象有好处吗?反之亦然?
当前回答
Observable对象表示一个基于推的集合。
观察者和可观察接口为基于推送的通知提供了一种通用机制,也称为观察者设计模式。Observable对象表示发送通知的对象(提供者);Observer对象表示接收它们的类(观察者)。
Subject类继承了Observable和Observer,也就是说它既是一个观察者又是一个可观察对象。您可以使用主题订阅所有观察者,然后将主题订阅到后端数据源
var subject = new Rx.Subject();
var subscription = subject.subscribe(
function (x) { console.log('onNext: ' + x); },
function (e) { console.log('onError: ' + e.message); },
function () { console.log('onCompleted'); });
subject.onNext(1);
// => onNext: 1
subject.onNext(2);
// => onNext: 2
subject.onCompleted();
// => onCompleted
subscription.dispose();
更多信息https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/subjects.md
其他回答
观察:每个观察者的结果不同
一个非常非常重要的区别。因为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 ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
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仅用于订阅数据更改。Subject还可以用于将数据更改通知订阅者(使用next()方法)。下面是一个小的可观察的模式实现,它可能有助于您理解这个概念。打印稿操场
我在例子中没有看到的一件事是,当你通过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);
可观察对象和主体都是可观察对象,这意味着观察者可以跟踪它们。它们都有一些独特的特点。有三种类型的科目,每一种也有独特的特点。
您可以在stackblitz上找到实际示例。 (您需要检查控制台以查看实际输出)
观察
它们是冷的:当它们至少有一个观察者时,代码就会被执行。
创建数据副本:Observable为每个观察者创建数据副本。
单向:观察者不能给观察对象赋值(源/主)。
主题
它们很热:即使没有观察者,代码也会被执行,值也会被传播。
共享数据:在所有观察者之间共享相同的数据。
双向:观察者可以给观察对象赋值(源/主)。
如果你正在使用subject,那么你会错过所有在创建观察者之前传播的值。这就是重放主题
ReplaySubject
它们很热:即使没有观察者,代码也会被执行,值也会被传播。
共享数据:在所有观察者之间共享相同的数据。
双向:观察者可以给观察对象赋值(源/主)。+
重播消息流:无论您何时订阅重播主题,您都将收到所有的广播消息。
在Subject和ReplaySubject中,不能将初始值设置为observable。这就是行为主体…
BehaviorSubject
它们很热:即使没有观察者,代码也会被执行,值也会被传播。
共享数据:在所有观察者之间共享相同的数据。
双向:观察者可以给观察对象赋值(源/主)。+
重播消息流:无论您何时订阅重播主题,您都将收到所有的广播消息。
你可以设置初始值:你可以用默认值初始化可观察对象。