В чем разница между субъектом и поведением субъекта?
Я не понимаю разницу между субъектом и поведенческим субъектом. Это просто, что BehaviorSubject имеет функцию getValue?
10 ответов
BehaviorSubject содержит одно значение. Когда он подписан, он немедленно выдает значение. Субъект не имеет значения.
Пример темы (с RxJS 5 API):
const subject = new Rx.Subject();
subject.next(1);
subject.subscribe(x => console.log(x));
Консольный вывод будет пустым
Пример поведения субъекта:
const subject = new Rx.BehaviorSubject();
subject.next(1);
subject.subscribe(x => console.log(x));
Консольный вывод: 1
К тому же:
- BehaviorSubject может быть создан с начальным значением: new Rx.BehaviorSubject(1)
- Рассмотрите ReplaySubject, если вы хотите, чтобы тема содержала более одного значения
BehaviourSubject
BehaviourSubject вернет начальное значение или текущее значение в подписке
var subject = new Rx.BehaviorSubject(0); // 0 is the initial value
subject.subscribe({
next: (v) => console.log('observerA: ' + v) // output initial value, then new values on `next` triggers
});
subject.next(1); // output new value 1 for 'observer A'
subject.next(2); // output new value 2 for 'observer A', current value 2 for 'Observer B' on subscription
subject.subscribe({
next: (v) => console.log('observerB: ' + v) // output current value 2, then new values on `next` triggers
});
subject.next(3);
С выходом:
observerA: 0
observerA: 1
observerA: 2
observerB: 2
observerA: 3
observerB: 3
Предмет
Тема не возвращает текущее значение в подписке. Срабатывает только на .next(value)
вызов и возврат / вывод value
var subject = new Rx.Subject();
subject.next(1); //Subjects will not output this value
subject.subscribe({
next: (v) => console.log('observerA: ' + v)
});
subject.subscribe({
next: (v) => console.log('observerB: ' + v)
});
subject.next(2);
subject.next(3);
Со следующим выводом на консоль:
observerA: 2
observerB: 2
observerA: 3
observerB: 3
Я только что создал проект, который объясняет, в чем разница между всеми предметами:
https://github.com/piecioshka/rxjs-subject-vs-behavior-vs-replay-vs-async
A содержит одно значение (поэтому нам действительно нужно инициализировать значение по умолчанию). Когда он подписан, он немедленно выдает это значение . A, с другой стороны, не имеет значения.
На самом деле это означает, что подписчики будут получать только предстоящее значение , тогда как подписчики получат предыдущее значение, а также предстоящее значение .
Подробнее о разнице между и
Subject
можно найти здесь
Итак, давайте возьмем пример, чтобы увидеть, как это будет себя вести:
let mySubject = new Subject<number>();
mySubject.subscribe(x => console.log("The first Subscription : " + x));
mySubject.next(1);
mySubject.next(2);
mySubject.subscribe(x => console.log("The second Subscription : " + x));
mySubject.next(3);
// The first Subscription : 1
// The first Subscription : 2
// The first Subscription : 3
// The second Subscription : 3
Как мы видели выше, первые 2 значения были выведены из субъекта до регистрации второй подписки, поэтому он их не получил, он получил новые значения только после подписки. Первая подписка получила их все, так как она подписалась до того, как были выведены первые значения.
Теперь давайте изменим
subject
и увидеть разницу:
let mySubject = new BehaviorSubject<number>(0);
mySubject.subscribe((x) => console.log('The first Subscription : ' + x));
mySubject.next(1);
mySubject.next(2);
mySubject.subscribe((x) => console.log('The second Subscription : ' + x));
mySubject.next(3);
// The first Subscription : 0 (since it's the initial value)
// The first Subscription : 1
// The first Subscription : 2
// The second Subscription : 2 (since it's the initial value for the seconde subscriber)
// The first Subscription : 3
// The second Subscription : 3
Теперь обратите внимание, как первый подписчик выводит с момента
BehaviorSubject
был инициализирован с
0
. Когда второй подписчик подписывается, он немедленно выдает значение «2», так как это было последнее значение, которое нужно было обработать, поэтому оно действует для него как начальное значение.
BehaviorSubject
сохраняет в памяти последнее значение, которое было испущено наблюдаемым. ОбычныйSubject
нет.
BehaviorSubject
как ReplaySubject
с размером буфера 1.
Это может помочь вам понять.
import * as Rx from 'rxjs';
const subject1 = new Rx.Subject();
subject1.next(1);
subject1.subscribe(x => console.log(x)); // will print nothing -> because we subscribed after the emission and it does not hold the value.
const subject2 = new Rx.Subject();
subject2.subscribe(x => console.log(x)); // print 1 -> because the emission happend after the subscription.
subject2.next(1);
const behavSubject1 = new Rx.BehaviorSubject(1);
behavSubject1.next(2);
behavSubject1.subscribe(x => console.log(x)); // print 2 -> because it holds the value.
const behavSubject2 = new Rx.BehaviorSubject(1);
behavSubject2.subscribe(x => console.log('val:', x)); // print 1 -> default value
behavSubject2.next(2) // just because of next emission will print 2
Все три совершенно разные, позвольте мне привести здесь еще несколько образцов,
const subject = new Rx.Subject();
const behaviorSubject = new Rx.BehaviorSubject([]);
const relaySubject = new Rx.ReplaySubject();
subject.next(1)
behaviorSubject.next(1);
behaviorSubject.next(2);
behaviorSubject.next(3);
relaySubject.next(1);
relaySubject.next(2);
relaySubject.next(3);
subject.subscribe(val => console.log('From Subject', val)); // this will not emits
behaviorSubject.subscribe(val => console.log('From BehaviorSubject', val)); // this will emits only last value
relaySubject.subscribe(val => console.log('From ReplaySubject', val)); // this will emit all values
Как вы можете видеть, когда мы подписываемся на субъект после того, как мы выдали (т.е. следующий (...)),
- тема - это вообще не уволят
- behaviorSubject — это сработает один раз с последним значением
- ReplaySubject — сработает 3 раза, сколько у нас есть
Таким образом, разница в основном заключается в том, где вы подписываетесь, будь то до или после .
На практике мы запускаем события только послеnext()
[т.е. после того, как мы заполним данные субъектами].
BehaviorSubject выдает значение после подписки, а Предмет нет.
// Subject
const mySubject = new Rx.Subject().subscribe((v) => console.log(v)); // will return nothing
// BehaviorSubject
const myBehaviorSubject = new Rx.BehaviorSubject(666).subscribe((v) => console.log(v)); // will return 666 when subscription occurs
Программа для тестирования всех 4 типов объектов: Subject, BehaviorSubject, ReplaySubject и AsyncSubject.
// 1. Subject - only value after subscribed
var subject = new Subject();
subject.next(1);
subject.next(2);
subject.complete();
subject.subscribe(
(data) => this.log("Subject="+data),
(error) => this.log(error),
() => this.log('Complete Subject')
);
subject.next(3);
subject.next(4);
// 2. BehaviorSubject - only last value before subscribed and all after subscription
// calls on initalization, mandatory to specify a value
var subjectb = new BehaviorSubject<any>(5);
subjectb.next(1);
subjectb.next(2);
subjectb.complete();
subjectb.subscribe(
(data) => this.log("Behavior="+data),
(error) => this.log(error),
() => this.log('Complete Behavior')
);
// 3. ReplaySubject - all specified last values before subscribed and all after subscription
// Does not call on initalization, no default value
var subjectr = new ReplaySubject(5);
subjectr.next(1);
subjectr.next(2);
subjectr.complete();
subjectr.subscribe(
(data) => this.log("Replay="+data),
(error) => this.log(error),
() => this.log('Complete Replay')
);
// 4. AsyncSubject - only last values before calling complete
var subjecta = new AsyncSubject();
subjecta.next(1);
subjecta.next(2);
subjecta.complete();
subjecta.subscribe(
(data) => this.log("Async="+data),
(error) => this.log(error),
() => this.log('Complete Async')
);
https://stackblitz.com/edit/example-rxjs-subject-e8vj9y?embed=1&amp;file=app/app.component.ts
BehaviorSubject keeps in memory the last value that was emitted by the observable. A regular Subject doesn't. So we can update dynamic titles based on Behaviour Subject.
var bSubject= new Rx.BehaviorSubject(0); // 0 is the initial value
bSubject.subscribe({
next: (v) => console.log('observerA: ' + v) // output initial value, then new values on `next` triggers
});
bSubject.next(1); // output new value 1 for 'observer A'
bSubject.next(2); // output new value 2 for 'observer A', current value 2 for 'Observer B' on subscription
bSubject.subscribe({
next: (v) => console.log('observerB: ' + v) // output current value 2, then new values on `next` triggers
});
bSubject.next(3);
- With Output