BehaviorSubject vs Observable?
我在研究角度rxjs模式,我不理解
据我所知,
你什么时候使用
行为主题是一种主题类型,主题是一种特殊的可观察类型,因此您可以像订阅任何其他可观察的消息一样订阅消息。行为主体的独特特征是:
- 它需要一个初始值,因为它必须始终在订阅时返回一个值,即使它没有收到
next() 。 - 订阅后,返回主题的最后一个值。只有当它接收到一个
onnext 时,才触发一个常规的可观察的触发器。 - 在任何时候,都可以使用
getValue() 方法在不可见代码中检索主题的最后一个值。
与观察对象相比,受试者的独特特征是:
- 它是一个观察者,除了是一个可观察的,所以除了订阅它之外,您还可以向一个主题发送值。
此外,你可以使用
observable是一个通用的,
BehaviorSubject示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // Behavior Subject // a is an initial value. if there is a subscription // after this, it would get"a" value immediately let bSubject = new BehaviorSubject("a"); bSubject.next("b"); bSubject.subscribe(value => { console.log("Subscription got", value); // Subscription got b, // ^ This would not happen // for a generic observable // or generic subject by default }); bSubject.next("c"); // Subscription got c bSubject.next("d"); // Subscription got d |
号
例2:常规主题:
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Regular Subject let subject = new Subject(); subject.next("b"); subject.subscribe(value => { console.log("Subscription got", value); // Subscription wont get // anything at this point }); subject.next("c"); // Subscription got c subject.next("d"); // Subscription got d |
使用
唯一的区别是,不能使用
在Angular服务中,我将使用
可观察:每个观察者的结果不同
一个非常重要的区别。因为Observable只是一个函数,它没有任何状态,所以对于每个新的观察者,它会一次又一次地执行Observable创建代码。这将导致:
The code is run for each observer
. If its a HTTP call, it gets called for each observer
号
这会导致严重的错误和效率低下
BehaviorSubject(或Subject)存储观察者详细信息,只运行一次代码,并将结果提供给所有观察者。
前任:
jsbin:http://jsbin.com/qowulet/edit?JS,控制台
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // --- 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)); |
。
1 | <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.3/Rx.min.js"> |
输出:
1 2 3 4 | "observer 1: 0.7184075243594013" "observer 2: 0.41271850211336103" "observer subject 1: 0.8034263165479893" "observer subject 2: 0.8034263165479893" |
。
观察使用
总结其他差异。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ 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 │ └─────────────────────────────────────┴─────────────────────────────────────┘ |
。
Observable对象表示基于推送的集合。
观察者和可观察的接口为基于推送的通知提供了一种通用机制,也称为观察者设计模式。可观察对象表示发送通知的对象(提供者);观察对象表示接收通知的类(观察者)。
主体类继承了可观察和可观察两种类型,即它既是观察者又是可观察者。您可以使用主题订阅所有观察者,然后将主题订阅到后端数据源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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
可观测的和主体都是可观测的,这意味着观察者可以跟踪它们。但它们都有一些独特的特点。此外,共有3种类型的受试者,每种受试者都具有独特的特征。让我们试着理解每一个。
你可以在Stackblitz上找到一个实际的例子。(您需要检查控制台以查看实际输出)
。
埃多克斯1〔22〕
它们是冷的:代码在列表中执行,它们只有一个观察者。
创建数据副本:Observable为每个观察者创建数据副本。
单向:观察者不能将值赋给可观察的(原始/主)。
江户十一〔一〕号
它们是热的:代码被执行,值被广播,即使没有观察者。
共享数据:所有观察者共享相同的数据。
双向:观察者可以将值分配给可观察的(原始/主)。
如果使用的是"使用主题",那么在创建观察者之前,您会错过所有已浏览的值。重放主题来了
埃多克斯1〔24〕
它们是热的:代码被执行,值被广播,即使没有观察者。
共享数据:所有观察者共享相同的数据。
双向:观察者可以将值分配给可观察的(原始/主)。加
重播消息流:无论您何时订阅重播主题,都将收到所有brodcasted消息。
在Subject和Replay Subject中,不能将初始值设置为Observable。所以行为主体来了
埃多克斯1〔25〕
它们是热的:代码被执行,值被广播,即使没有观察者。
共享数据:所有观察者共享相同的数据。
双向:观察者可以将值分配给可观察的(原始/主)。加
重播消息流:无论您何时订阅重播主题,都将收到所有brodcasted消息。
您可以设置初始值:您可以用默认值初始化Observable。
我在示例中没有看到的一件事是,当您通过asobservable将BehaviorSubject强制转换为Observable时,它继承了在订阅时返回最后一个值的行为。
这是一个棘手的问题,因为库通常会公开可观察的字段(即Angular2中ActivateDroute中的参数),但可能会在幕后使用主题或行为主题。他们使用什么会影响订阅的行为。
请参见http://jsbin.com/ziquxapubo/edit?HTML、JS、控制台
1 2 3 4 5 6 7 8 9 10 11 | 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); |
Observable只允许订阅,而Subject允许发布和订阅。
因此,主题允许您的服务同时用作发布服务器和订阅服务器。
到目前为止,我对
让我们用一个有角度的cli示例更好地理解它。运行以下命令:
1 2 3 4 5 6 7 | npm install -g @angular/cli ng new angular2-subject cd angular2-subject ng serve |
将
1 2 3 4 5 | {{message}} </app-home> |
号
运行命令
1 2 | <input type="text" placeholder="Enter message" #message> <button type="button" (click)="setMessage(message)">Send message</button> |
运行此命令
将
1 2 3 4 5 6 7 8 9 10 11 12 | import { Injectable } from '@angular/core'; import { Subject } from 'rxjs/Subject'; @Injectable() export class MessageService { public message = new Subject<string>(); setMessage(value: string) { this.message.next(value); //it is publishing this value to all the subscribers that have already subscribed to this message } } |
。
现在,在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import { Component } from '@angular/core'; import { MessageService } from '../../service/message.service'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.css'] }) export class HomeComponent { constructor(public messageService:MessageService) { } setMessage(event) { console.log(event.value); this.messageService.setMessage(event.value); } } |
在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import { Component, OnDestroy } from '@angular/core'; import { MessageService } from './service/message.service'; import { Subscription } from 'rxjs/Subscription'; @Component({ selector: 'app-root', templateUrl: './app.component.html' }) export class AppComponent { message: string; subscription: Subscription; constructor(public messageService: MessageService) { } ngOnInit() { this.subscription = this.messageService.message.subscribe( (message) => { this.message = message; } ); } ngOnDestroy() { this.subscription.unsubscribe(); } } |
。
就这样。
现在,任何输入到
应用组件.ts
1 | behaviourService.setName("behaviour"); |
。
行为.服务.ts
1 2 3 4 5 6 7 8 | private name = new BehaviorSubject(""); getName = this.name.asObservable();` constructor() {} setName(data) { this.name.next(data); } |
自定义组件.ts
1 2 3 | behaviourService.subscribe(response=>{ console.log(response); //output: behaviour }); |
。
BehaviorSubject与Observable:RXJS有观察者和可观察者,RXJS提供了一个用于数据流的多个类,其中一个是BehaviorSubject。
观察:观察是一段时间内多个值的惰性集合。
BehaviorSubject:需要初始值并将其当前值发送给新订户的主题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // RxJS v6+ import { BehaviorSubject } from 'rxjs'; const subject = new BehaviorSubject(123); //two new subscribers will get initial value => output: 123, 123 subject.subscribe(console.log); subject.subscribe(console.log); //two subscribers will get new value => output: 456, 456 subject.next(456); //new subscriber will get latest value (456) => output: 456 subject.subscribe(console.log); //all three subscribers will get new value => output: 789, 789, 789 subject.next(789); // output: 123, 123, 456, 456, 456, 789, 789, 789 |