Estoy investigando los patrones de Angular RxJ y no entiendo la diferencia entre a BehaviorSubject
y an Observable
.
Según tengo entendido, a BehaviorSubject
es un valor que puede cambiar con el tiempo (se puede suscribir y los suscriptores pueden recibir resultados actualizados). Este parece ser exactamente el mismo propósito de un Observable
.
¿Cuándo Observable
usarías un vs a BehaviorSubject
? ¿Hay beneficios de usar un BehaviorSubject
over an Observable
o viceversa?
BehaviorSubject es un tipo de sujeto, un sujeto es un tipo especial de observable, por lo que puede suscribirse a mensajes como cualquier otro observable. Las características únicas de BehaviorSubject son:
next()
onnext
getValue()
método.Las características únicas de un sujeto en comparación con un observable son:
Además, puede obtener un comportamiento observable del sujeto utilizando el asObservable()
método en BehaviorSubject
.
Observable es un genérico y BehaviorSubject
técnicamente es un subtipo de observable porque BehaviorSubject es un observable con cualidades específicas.
Ejemplo con 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
Ejemplo 2 con tema regular:
// 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
Se puede crear un observable a partir de ambos Subject
y BehaviorSubject
utilizando subject.asObservable()
.
La única diferencia es que no puede enviar valores a un next()
método de uso observable .
En los servicios angulares, lo usaría BehaviorSubject
para un servicio de datos ya que un servicio angular a menudo se inicializa antes de que el componente y el sujeto del comportamiento garanticen que el componente que consume el servicio reciba los últimos datos actualizados incluso si no hay nuevas actualizaciones desde la suscripción del componente a estos datos
Una diferencia muy importante. Dado que Observable es solo una función, no tiene ningún estado, por lo que para cada nuevo Observer, ejecuta el código de creación observable una y otra vez. Esto resulta en:
El código se ejecuta para cada observador. Si es una llamada HTTP, se llama para cada observador
Esto causa errores e ineficiencias importantes
BehaviorSubject (o Subject) almacena los detalles del observador, ejecuta el código solo una vez y da el resultado a todos los observadores.
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>
Salida:
"observer 1: 0.7184075243594013"
"observer 2: 0.41271850211336103"
"observer subject 1: 0.8034263165479893"
"observer subject 2: 0.8034263165479893"
Observe cómo el uso Observable.create
creó una salida diferente para cada observador, pero BehaviorSubject
dio la misma salida para todos los observadores. Esto es importante.
Otras diferencias resumidas.
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 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 y sujeta ambos son medios de observables un observador puede realizar un seguimiento de ellos. pero ambos tienen algunas características únicas. Además, hay un total de 3 tipos de temas, cada uno de ellos nuevamente tiene características únicas. intentemos comprender cada uno de ellos.
puede encontrar el ejemplo práctico aquí en stackblitz . (Debe verificar la consola para ver la salida real)
Observables
Son fríos: el código se ejecuta cuando tienen al menos un observador.
Crea una copia de los datos: Observable crea una copia de los datos para cada observador.
Unidireccional: el observador no puede asignar valor a observable (origen / maestro).
Subject
Están calientes: el código se ejecuta y el valor se transmite incluso si no hay un observador.
Comparte datos: los mismos datos se comparten entre todos los observadores.
bidireccional: el observador puede asignar valor a lo observable (origen / maestro).
Si está utilizando un sujeto, se pierde todos los valores que se transmiten antes de la creación del observador. Entonces aquí viene Replay Subject
ReplaySubject
Están calientes: el código se ejecuta y el valor se transmite incluso si no hay un observador.
Comparte datos: los mismos datos se comparten entre todos los observadores.
bidireccional: el observador puede asignar valor a lo observable (origen / maestro). más
Reproducir el flujo de mensajes: no importa cuándo se suscriba al tema de la reproducción, recibirá todos los mensajes transmitidos.
En sujeto y sujeto de repetición no se puede establecer el valor inicial como observable. Entonces aquí viene el sujeto conductual
BehaviorSubject
Están calientes: el código se ejecuta y el valor se transmite incluso si no hay un observador.
Comparte datos: los mismos datos se comparten entre todos los observadores.
bidireccional: el observador puede asignar valor a lo observable (origen / maestro). más
Reproducir el flujo de mensajes: no importa cuándo se suscriba al tema de la reproducción, recibirá todos los mensajes transmitidos.
Puede establecer el valor inicial: puede inicializar el observable con el valor predeterminado.
El objeto Observable representa una colección basada en push.
Las interfaces Observer y Observable proporcionan un mecanismo generalizado para notificaciones push, también conocido como patrón de diseño del observador. El objeto Observable representa el objeto que envía notificaciones (el proveedor); el objeto Observer representa la clase que los recibe (el observador).
La clase Sujeto hereda tanto Observable como Observer, en el sentido de que es tanto un observador como un observable. Puede usar un tema para suscribir a todos los observadores y luego suscribir el tema a una fuente de datos de back-end.
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();
Más en https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/subjects.md
Una cosa que no veo en los ejemplos es que cuando lanza BehaviorSubject a Observable a través de asObservable, hereda el comportamiento de devolver el último valor en la suscripción.
Es la parte complicada, ya que a menudo las bibliotecas exponen campos como observables (es decir, params en ActivatedRoute en Angular2), pero pueden usar Subject o BehaviorSubject detrás de escena. Lo que usan afectaría el comportamiento de suscripción.
Ver aquí 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);
Un observable le permite suscribirse solo, mientras que un tema le permite publicar y suscribirse.
Por lo tanto, un tema permite que sus servicios se utilicen tanto como editor como como suscriptor.
A partir de ahora, no soy tan bueno, Observable
así que solo compartiré un ejemplo de Subject
.
Entendamos mejor con un ejemplo de CLI angular . Ejecute los siguientes comandos:
npm install -g @angular/cli
ng new angular2-subject
cd angular2-subject
ng serve
Reemplace el contenido de app.component.html
con:
<div *ngIf="message">
{{message}}
</div>
<app-home>
</app-home>
Ejecute el comando ng g c components/home
para generar el componente de inicio. Reemplace el contenido de home.component.html
con:
<input type="text" placeholder="Enter message" #message>
<button type="button" (click)="setMessage(message)" >Send message</button>
#message
es la variable local aquí. Agrega una propiedad message: string;
a la app.component.ts
clase de.
Ejecute este comando ng g s service/message
. Esto generará un servicio en src\app\service\message.service.ts
. Proporcione este servicio a la aplicación .
Importar Subject
a MessageService
. Agrega un tema también. El código final se verá así:
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
}
}
Ahora, inyecte este servicio home.component.ts
y pase una instancia del mismo al constructor. Haz esto app.component.ts
también. Utilice esta instancia de servicio para pasar el valor de #message
a la función de servicio 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);
}
}
En el interior app.component.ts
, suscríbase y cancele la suscripción (para evitar pérdidas de memoria) a 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();
}
}
Eso es.
Ahora, cualquier valor ingresado dentro #message
de home.component.html
se imprimirá hacia {{message}}
adentroapp.component.html
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
});
Piense en Observables como una tubería con agua que fluye, a veces fluye agua y otras no. En algunos casos, es posible que necesite una tubería que siempre tenga agua, puede hacer esto creando una tubería especial que siempre contenga agua sin importar cuán pequeña sea, llamemos a esta tubería especial BehaviorSubject , si resulta que es proveedor de suministro de agua en su comunidad, puede dormir tranquilo por la noche sabiendo que su tubería recién instalada simplemente funciona.
En términos técnicos: puede encontrar casos de uso en los que un Observable siempre debe tener valor, tal vez desee capturar el valor de un texto de entrada a lo largo del tiempo, luego puede crear una instancia de BehaviorSubject para garantizar este tipo de comportamiento, digamos:
const firstNameChanges = new BehaviorSubject("<empty>");
// pass value changes.
firstNameChanges.next("Jon");
firstNameChanges.next("Arya");
A continuación, puede utilizar "valor" para muestrear cambios a lo largo del tiempo.
firstNameChanges.value;
Esto es útil cuando combina Observables más tarde, al observar el tipo de su transmisión como BehaviorSubject, puede asegurarse de que la transmisión al menos se dispare o emita una señal al menos una vez .
BehaviorSubject vs Observable : RxJS tiene observadores y observables, Rxjs ofrece múltiples clases para usar con flujos de datos, y una de ellas es BehaviorSubject.
Observables : Los observables son colecciones perezosas de múltiples valores a lo largo del tiempo.
BehaviorSubject : un sujeto que requiere un valor inicial y emite su valor actual a los nuevos suscriptores.
// 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
Comportamiento Sujeto
BehaviorSubject se basa en la misma funcionalidad que nuestro ReplaySubject, como sujeto, caliente y reproduce el valor anterior.
BehaviorSubject agrega una pieza más de funcionalidad en la que puede darle un valor inicial a BehaviorSubject. Sigamos adelante y echemos un vistazo a ese código.
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');
Observables
Para comenzar, veremos la API mínima para crear un Observable regular. Hay un par de formas de crear un Observable. La forma en que crearemos nuestro Observable es instanciando la clase. Otros operadores pueden simplificar esto, pero querremos comparar el paso de instanciación con nuestros diferentes tipos observables.
import { Observable } from 'rxjs';
const observable = new Observable(observer => {
setTimeout(() => observer.next('hello from Observable!'), 1000);
});
observable.subscribe(v => console.log(v));
La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.
Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.
Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.
Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.
Hemos pirateado algunas ciudades industriales en esta columna, como Los Ángeles y Las Vegas. Ahora es el momento de una ciudad militar-industrial-compleja.
Un minorista está enlatando su sección de tallas grandes. Pero no están tomando la categoría solo en línea o descontinuándola por completo.
Entiendo totalmente, completamente si tienes una relación difícil con los animales de peluche. Son lindos, tienen valor sentimental y es difícil separarse de ellos.
El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.
Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".
Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.
Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.