it-swarm.com.de

BehaviorSubject vs Observable?

Ich untersuche Angular RxJs Muster und verstehe den Unterschied zwischen BehaviorSubject und Observable nicht.

Nach meinem Verständnis ist BehaviorSubject ein Wert, der sich im Laufe der Zeit ändern kann (abonniert werden kann und Abonnenten aktualisierte Ergebnisse erhalten können). Dies scheint genau der gleiche Zweck eines Observable zu sein.

Wann würden Sie ein Observable gegen ein BehaviorSubject verwenden? Gibt es Vorteile bei der Verwendung von BehaviorSubject gegenüber Observable oder umgekehrt?

539
Kevin Mark

BehaviorSubject ist eine Art von Betreff, ein Betreff ist eine spezielle Art von Beobachtungsobjekt, sodass Sie Nachrichten wie jedes andere Beobachtungsobjekt abonnieren können. Die einzigartigen Funktionen von BehaviorSubject sind:

  • Es benötigt einen Anfangswert, da es beim Abonnement immer einen Wert zurückgeben muss, auch wenn es kein next() erhalten hat.
  • Beim Abonnement wird der letzte Wert des Betreffs zurückgegeben. Ein reguläres Observable wird nur ausgelöst, wenn es ein onnext empfängt.
  • mit der Methode getValue() können Sie jederzeit den letzten Wert des Betreffs in einem nicht beobachtbaren Code abrufen.

Einzigartige Merkmale eines Subjekts im Vergleich zu einem beobachtbaren sind:

  • Es ist nicht nur ein Beobachter, sondern auch ein Beobachter, sodass Sie zusätzlich zum Abonnieren auch Werte an ein Subjekt senden können.

Darüber hinaus können Sie mithilfe der asObservable() -Methode für BehaviorSubject ein beobachtbares Verhalten von einem Subjekt abrufen.

Observable ist ein generischer Typ, und BehaviorSubject ist technisch gesehen ein Untertyp von Observable, da BehaviorSubject ein Observable mit bestimmten Eigenschaften ist.

Beispiel mit 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

Beispiel 2 mit regulärem Betreff:

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

Ein Observable kann sowohl aus Subject als auch BehaviorSubject mit subject.asObservable() erstellt werden.

Der einzige Unterschied besteht darin, dass Sie mit der Methode next() keine Werte an einen Observable senden können.

In Angular Diensten würde ich BehaviorSubject für einen Datendienst als angular Dienst verwenden, der häufig initialisiert wird, bevor die Komponente und das Verhaltenssubjekt sicherstellen, dass die den Dienst konsumierende Komponente die letzte Aktualisierung erhält Daten, auch wenn es seit dem Abonnement dieser Daten durch die Komponente keine neuen Aktualisierungen gibt.

796

Beobachtbar: Unterschiedliches Ergebnis für jeden Beobachter

Ein sehr sehr wichtiger Unterschied. Da Observable nur eine Funktion ist, hat es keinen Status. Daher führt es für jeden neuen Observer den Observable-Erstellungscode immer wieder aus. Das führt zu:

Der Code wird für jeden Beobachter ausgeführt. Wenn es sich um einen HTTP-Aufruf handelt, wird er für jeden Beobachter aufgerufen

Dies führt zu schwerwiegenden Fehlern und Ineffizienzen

BehaviorSubject (oder Subject) speichert Beobachterdetails, führt den Code nur einmal aus und gibt das Ergebnis an alle Beobachter weiter.

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>

Ausgabe :

"observer 1: 0.7184075243594013"
"observer 2: 0.41271850211336103"
"observer subject 1: 0.8034263165479893"
"observer subject 2: 0.8034263165479893"

Beobachten Sie, wie mit Observable.create für jeden Beobachter eine andere Ausgabe erstellt wurde, aber BehaviorSubject für alle Beobachter dieselbe Ausgabe ergab. Das ist wichtig.


Andere Unterschiede zusammengefasst.

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃         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                          │
└─────────────────────────────────────┴─────────────────────────────────────┘
136
Vamshi

Das Observable-Objekt repräsentiert eine Push-basierte Sammlung.

Die Observer- und Observable-Schnittstelle bieten einen allgemeinen Mechanismus für die Push-basierte Benachrichtigung, der auch als Observer-Entwurfsmuster bezeichnet wird. Das Observable-Objekt stellt das Objekt dar, das Benachrichtigungen sendet (der Anbieter). Das Observer-Objekt repräsentiert die Klasse, die sie empfängt (den Observer).

Die Subject-Klasse erbt sowohl Observable als auch Observer in dem Sinne, dass sie sowohl Observer als auch Observable ist. Sie können einen Betreff verwenden, um alle Beobachter zu abonnieren. Anschließend können Sie den Betreff für eine Back-End-Datenquelle abonnieren

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

Weitere Informationen finden Sie unter https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/subjects.md

26

Beobachtbares und Subjekt sind beides Beobachtbare Mittel, die ein Beobachter verfolgen kann. aber beide haben einige einzigartige Eigenschaften. Weiterhin gibt es insgesamt 3 Arten von Fächern, von denen jedes wiederum einzigartige Eigenschaften aufweist. Lassen Sie uns versuchen, jeden von ihnen zu verstehen.

das praktische Beispiel finden Sie hier auf stackblitz . (Sie müssen die Konsole überprüfen, um die tatsächliche Ausgabe zu sehen)

enter image description here

Observables

Sie sind kalt: Code wird ausgeführt, wenn sie mindestens einen einzelnen Beobachter haben.

Erstellt eine Kopie der Daten: Observable erstellt eine Kopie der Daten für jeden Beobachter.

Unidirektional: Der Beobachter kann dem beobachtbaren (Ursprung/Meister) keinen Wert zuweisen.

Subject

Sie sind heiß: Code wird ausgeführt und Wert wird gesendet, auch wenn kein Beobachter anwesend ist.

Daten werden geteilt: Die gleichen Daten werden von allen Beobachtern geteilt.

bidirektional: Beobachter kann beobachtbaren Werten (Ursprung/Meister) zuweisen.

Wenn Sie den Betreff verwenden, verpassen Sie alle Werte, die vor dem Erstellen des Beobachters gesendet werden. Also hier kommt Betreff wiederholen

ReplaySubject

Sie sind heiß: Code wird ausgeführt und Wert wird gesendet, auch wenn kein Beobachter anwesend ist.

Daten werden geteilt: Die gleichen Daten werden von allen Beobachtern geteilt.

bidirektional: Beobachter kann beobachtbaren Werten (Ursprung/Meister) zuweisen. Plus

Wiederholung des Nachrichtenstroms: Unabhängig davon, wann Sie den Betreff der Wiederholung abonnieren, erhalten Sie alle gesendeten Nachrichten .

In Betreff und Betreff wiedergeben können Sie den Anfangswert nicht auf beobachtbar setzen. Also hier kommt Verhaltensthema

BehaviorSubject

Sie sind heiß: Code wird ausgeführt und der Wert wird gesendet, auch wenn kein Beobachter anwesend ist.

Daten werden geteilt: Die gleichen Daten werden von allen Beobachtern geteilt.

bidirektional: Beobachter kann beobachtbaren Werten (Ursprung/Meister) zuweisen. Plus

Wiederholung des Nachrichtenstroms: Unabhängig davon, wann Sie den Betreff der Wiederholung abonnieren, erhalten Sie alle gesendeten Nachrichten .

Sie können den Anfangswert einstellen: Sie können das Observable mit dem Standardwert initialisieren.

25
Kedar9444

Eine Sache, die ich in Beispielen nicht sehe, ist, dass wenn Sie BehaviorSubject über asObservable in Observable umwandeln, es das Verhalten erbt, den letzten Wert bei der Subskription zurückzugeben.

Dies ist eine heikle Angelegenheit, da Bibliotheken häufig Felder als beobachtbar ausgeben (d. H. Parameter in ActivatedRoute in Angular2), aber möglicherweise Subject oder BehaviorSubject hinter den Kulissen verwenden. Was sie verwenden, würde das Abonnementverhalten beeinflussen.

Siehe hier 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);
16

Mit einem beobachtbar können Sie nur abonnieren, mit einem Betreff können Sie sowohl veröffentlichen als auch abonnieren.

Ein Betreff ermöglicht es also, dass Ihr Dienste sowohl als Herausgeber als auch als Abonnent verwendet wird.

Ab sofort bin ich nicht so gut in Observable, daher teile ich nur ein Beispiel für Subject.

Lassen Sie uns mit einem Angular CLI Beispiel besser verstehen. Führen Sie die folgenden Befehle aus:

npm install -g @angular/cli

ng new angular2-subject

cd angular2-subject

ng serve

Ersetzen Sie den Inhalt von app.component.html durch:

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

<app-home>
</app-home>

Führen Sie den Befehl ng g c components/home aus, um die Home-Komponente zu generieren. Ersetzen Sie den Inhalt von home.component.html durch:

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

#message ist hier die lokale Variable. Fügen Sie der Klasse von message: string; eine Eigenschaft app.component.ts hinzu.

Führen Sie diesen Befehl ng g s service/message aus. Dies erzeugt einen Dienst bei src\app\service\message.service.ts. Geben Sie diesen Dienst für die App an.

Subject in MessageService importieren. Fügen Sie auch einen Betreff hinzu. Der endgültige Code soll so aussehen:

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

Fügen Sie diesen Service nun in home.component.ts ein und übergeben Sie eine Instanz davon an den Konstruktor. Tun Sie dies auch für app.component.ts. Verwenden Sie diese Dienstinstanz, um den Wert von #message an die Dienstfunktion setMessage zu übergeben:

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

Melden Sie sich in app.component.ts beim Subject an und melden Sie sich ab (um Speicherverluste zu vermeiden):

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

Das ist es.

Jetzt wird jeder Wert, der in #message von home.component.html eingegeben wurde, in {{message}} in app.component.html gedruckt.

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 verfügt über Beobachter und Observables, Rxjs bietet mehrere Klassen zur Verwendung mit Datenströmen an, von denen eine ein BehaviorSubject ist.

Observables: Observables sind langsame Sammlungen von mehreren Werten im Laufe der Zeit.

BehaviorSubject: Ein Betreff, der einen Anfangswert benötigt und seinen aktuellen Wert an neue Abonnenten ausgibt.

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