web-dev-qa-db-ja.com

BehaviorSubjectとObservableの関係

Angular RxJsパターンを調べていますが、BehaviorSubjectname__とObservablename__の違いがわかりません。

私の理解したところでは、BehaviorSubjectname__は時間の経過とともに変わる可能性がある値です(購読することができ、購読者は更新された結果を受け取ることができます)。これはObservablename__とまったく同じ目的のようです。

Observablename__とBehaviorSubjectname__のどちらを使用するのですか。 BehaviorSubjectname__よりObservablename__を使用することに利点はありますか、またはその逆です。

488
Kevin Mark

BehaviorSubject は件名の一種です。件名は特別な種類の監視可能なので、他の監視可能なものと同じようにメッセージを購読できます。 BehaviorSubjectのユニークな機能は次のとおりです。

  • next()を受け取っていなくても常にサブスクリプションで値を返さなければならないため、初期値が必要です。
  • 購読時に、件名の最後の値を返します。通常の観測量はonnextを受け取ったときにのみトリガーされます
  • getValue()メソッドを使用すると、いつでも、観測できないコード内の件名の最後の値を取得できます。

観察可能物と比較した対象の独特の特徴は以下の通りです。

  • それは観察可能であることに加えて観察者ですので、あなたはそれを購読することに加えて主題に値を送ることもできます。

さらに、BehaviorSubjectasObservable()メソッドを使用して、行動の主観から観測量を得ることができます。

Observable は総称であり、BehaviorSubjectは特定の性質を持つオブザーバブルであるため、BehaviorSubjectは技術的にはObservableのサブタイプです。

BehaviorSubject :を使用した例

// 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

// 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

subject.asObservable()を使用して、SubjectBehaviorSubjectの両方からオブザーバブルを作成できます。

唯一の違いは、next()メソッドを使って観測量に値を送ることができないということです。

Angularサービスでは、コンポーネントと振る舞いサブジェクトが確実にサービスを消費するコンポーネントが最後の更新されたデータを受け取ることを保証する前に初期化する前にアンギュラサービスが初期化されるのでデータサービスにBehaviorSubjectを使います。このデータに対するコンポーネントのサブスクリプション。

743

観測可能量:観測者ごとに異なる結果

非常に重要な違いが1つあります。 Observableは単なる関数なので、状態はありません。したがって、新しいObserverごとに、observable createコードを何度も実行します。これは次のようになります。

コードは各オブザーバに対して実行されます。 HTTP呼び出しの場合は、オブザーバごとに呼び出されます。

これは大きなバグと非効率性を引き起こします

BehaviorSubject(またはSubject)は、オブザーバの詳細を格納し、コードを1回だけ実行して結果をすべてのオブザーバに渡します。

例:

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                          │
└─────────────────────────────────────┴─────────────────────────────────────┘
125
Vamshi

Observableオブジェクトは、プッシュベースのコレクションを表します。

ObserverおよびObservableインターフェースは、オブザーバデザインパターンとも呼ばれる、プッシュベースの通知のための一般化されたメカニズムを提供します。 Observableオブジェクトは、通知を送信するオブジェクト(プロバイダ)を表します。 Observerオブジェクトはそれらを受け取るクラス(オブザーバ)を表します。

Subjectクラスは、オブザーバとオブザーバブルの両方を継承しています。サブジェクトを使用してすべてのオブザーバを購読してから、そのサブジェクトをバックエンドデータソースに購読することができます。

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

25

例では見られないことの1つは、asObservableを介してBehaviorSubjectをObservableにキャストすると、サブスクリプションで最後の値を返すという動作を継承することです。

ライブラリはフィールドを観察可能として公開することが多いので(つまりAngular 2のActivatedRouteのparams)、裏側では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);
15

Observable subject はどちらも観測可能であり、オブザーバがそれらを追跡できることを意味します。しかし、どちらもいくつかのユニークな特徴があります。さらに合計3つのタイプの主題があり、それらのそれぞれもまた独特の特性を持っています。それぞれを理解しようとしましょう。

実際の例は stackblitz にあります。 (実際の出力を見るためにはコンソールをチェックする必要があります)

enter image description here

Observables

寒いです:コードはリスト内で実行され、単一のオブザーバを持ちます。

データのコピーを作成します。Observableは、オブザーバごとにデータのコピーを作成します。

単方向:オブザーバは、観測可能値に値を割り当てることができません(Origin/master)。

Subject

彼らは暑い:コードが実行され、オブザーバがいなくてもvalueがブロードキャストされます。

Shares data:すべてのオブザーバ間で同じデータが共有されます。

双方向:オブザーバは観測値に値を代入することができます(Origin/master)。

件名を使用している場合は、オブザーバの作成前に宣伝されているすべての値を見逃しています。だからここに来る リプレイの件名

Replay Subject

彼らは暑い:コードが実行され、オブザーバがいなくてもvalueがブロードキャストされます。

Shares data:すべてのオブザーバ間で同じデータが共有されます。

双方向:オブザーバは観測値に値を代入することができます(Origin/master)。プラス

メッセージストリームを再生します。再生の件名を購読しても、すべてのメッセージが配信されます。

件名および再生件名では、初期値をobservableに設定することはできません。だからここに来る 行動の件名

Behavioral Subject

彼らは暑い:コードが実行され、オブザーバがいなくてもvalueがブロードキャストされます。

Shares data:すべてのオブザーバ間で同じデータが共有されます。

双方向:オブザーバは観測値に値を代入することができます(Origin/master)。プラス

メッセージストリームを再生します。再生の件名を購読しても、すべてのメッセージが配信されます。

初期値を設定できますオブザーバブルをデフォルト値で初期化できます。

13
Kedar9444

observable を使用すると購読のみが可能になり、 subject を使用すると公開と購読の両方が可能になります。

そのため、件名によってあなたの services を出版者と購読者の両方として使うことができます。

今のところ、私はObservableがあまり得意ではないので、Subjectの例だけを共有します。

Angular CLI の例で、よりよく理解しましょう。以下のコマンドを実行してください。

npm install -g @angular/cli

ng new angular2-subject

cd angular2-subject

ng serve

app.component.htmlの内容を次のように置き換えます。

<div *ngIf="message">
  {{message}}
</div>

<app-home>
</app-home>

ng g c components/homeコマンドを実行してホームコンポーネントを生成します。 home.component.htmlの内容を次のように置き換えます。

<input type="text" placeholder="Enter message" #message>
<button type="button" (click)="setMessage(message)" >Send message</button>

ここでは#messageがローカル変数です。プロパティmessage: string;app.component.tsのクラスに追加します。

このコマンドng g s service/messageを実行してください。これはsrc\app\service\message.service.tsにサービスを生成します。 このサービスをアプリに提供する

SubjectMessageServiceにインポートします。件名も追加してください。最終的なコードは次のようになります。

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

さて、このサービスをhome.component.tsにインジェクトし、そのインスタンスをコンストラクタに渡します。 app.component.tsでもこれを行います。このサービスインスタンスを使用して、#messageの値をサービス関数setMessageに渡します。

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

app.component.ts内で、(メモリリークを防ぐために)Subjectを購読および購読解除します。

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

それでおしまい。

これで、#messagehome.component.html内に入力された値は、{{message}}内のapp.component.htmlに出力されます。

9
student

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
});
2
Chandru Dev

BehaviorSubject vs Observable :RxJSにはオブザーバとオブザーバブルがあり、Rxjsにはデータストリームで使用する複数のクラスがあり、その1つがBehaviorSubjectです。

オブザーバブル :オブザーバブルは、時間の経過とともに複数の値が集まったものです。

BehaviorSubject :初期値が必要で、現在の値を新しい購読者に送信する件名。

 // 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
0
Flash