observables example ejemplo angular rxjs behaviorsubject

example - observables angular 4



BehaviorSubject vs Observable? (8)

Estoy investigando los patrones de Angular RxJs y no entiendo la diferencia entre un BehaviorSubject y un Observable .

Según tengo entendido, un BehaviorSubject es un valor que puede cambiar con el tiempo (puede suscribirse y los suscriptores pueden recibir resultados actualizados). Este parece ser exactamente el mismo propósito de un Observable .

¿Cuándo Observable un Observable vs un BehaviorSubject ? ¿Existen beneficios al usar un BehaviorSubject sobre un Observable o viceversa?


Observable: resultado diferente para cada observador

Una diferencia muy muy importante. Como Observable es solo una función, no tiene ningún estado, por lo que para cada nuevo Observador, 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 importantes e ineficiencias.

BehaviorSubject (o Subject) almacena 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 de Observable.create creó resultados diferentes para cada observador, pero BehaviorSubject dio el mismo resultado 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 │ └─────────────────────────────────────┴─────────────────────────────────────┘


El objeto Observable representa una colección basada en inserción.

Las interfaces de observador y observable proporcionan un mecanismo generalizado para notificaciones basadas en notificaciones, también conocido como patrón de diseño de observador. El objeto Observable representa el objeto que envía notificaciones (el proveedor); el objeto Observador representa la clase que los recibe (el observador).

La clase Asunto hereda tanto Observable como Observador, en el sentido de que es a la vez observador y observable. Puede usar un tema para suscribir a todos los observadores y luego suscribir el tema a una fuente de datos de fondo

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


Un observable permite suscribirse solo, mientras que un subject permite publicar y suscribirse.

Por lo tanto, un tema permite que sus services se utilicen como editor y como suscriptor.

A partir de ahora, no soy tan bueno en Observable así que compartiré solo un ejemplo de Subject .

Comprendamos 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 gc 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í. Agregue un message: string; propiedad message: string; a la clase de app.component.ts .

Ejecute este comando ng gs service/message . Esto generará un servicio en src/app/service/message.service.ts . Proporcionar este servicio a la aplicación .

Importar Subject en 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 en home.component.ts y pase una instancia al constructor. Haga esto también para app.component.ts . Use 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); } }

Dentro de app.component.ts , suscríbase y anule la suscripción (para evitar pérdidas de memoria) al 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 del #message de home.component.html se imprimirá en {{message}} dentro de app.component.html


Una cosa que no veo en los ejemplos es que cuando lanza BehaviorSubject to Observable a través de asObservable, hereda el comportamiento de devolver el último valor en la suscripción.

Es un poco complicado, ya que a menudo las bibliotecas exponen los campos como observables (es decir, parámetros en ActivatedRoute en Angular2), pero pueden usar Subject o BehaviorSubject detrás de escena. Lo que usan afectaría el comportamiento de la 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);


BehaviorSubject es un tipo de asunto, un asunto es un tipo especial de observable para que pueda suscribirse a mensajes como cualquier otro observable. Las características únicas de BehaviorSubject son:

  • Necesita un valor inicial ya que siempre debe devolver un valor en la suscripción, incluso si no ha recibido un next()
  • Tras la suscripción, devuelve el último valor del tema. Un observable regular solo se dispara cuando recibe un onnext
  • en cualquier momento, puede recuperar el último valor del sujeto en un código no observable utilizando el método getValue() .

Las características únicas de un sujeto en comparación con un observable son:

  • Es un observador además de ser un observable, por lo que también puede enviar valores a un sujeto además de suscribirse a él.

Además, puede obtener un sujeto de comportamiento observable utilizando el método asObservable() en BehaviorSubject .

Observable es un genérico, y BehaviorSubject es técnicamente 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 sujeto 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 desde Subject y BehaviorSubject mediante subject.asObservable() .

La única diferencia es que no puede enviar valores a un observable utilizando el método next() .

En los servicios angulares, 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 de 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.


BehaviorSubject vs Observable : RxJS tiene observadores y observables, Rxjs ofrece múltiples clases para usar con flujos de datos, y uno de ellos es BehaviorSubject.

Observables : los observables son colecciones diferidas 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


Observable y sujeto son ambos observables significa que un observador puede rastrearlos. 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. Tratemos de entender 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 solo observador.

Crea una copia de datos: Observable crea una copia de 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 observador.

Datos compartidos: se comparten los mismos datos entre todos los observadores.

bidireccional: el observador puede asignar valor a observable (origen / maestro).

Si está utilizando el sujeto, pierde todos los valores que se transmiten antes de la creación del observador. Así que aquí viene el tema de repetición

ReplaySubject

Están calientes: el código se ejecuta y el valor se transmite incluso si no hay observador.

Datos compartidos: se comparten los mismos datos entre todos los observadores.

bidireccional: el observador puede asignar valor a observable (origen / maestro). más

Reproduzca el flujo de mensajes: no importa cuándo se suscriba el asunto de reproducción, recibirá todos los mensajes emitidos.

En el asunto y el tema de reproducción no puede establecer el valor inicial en observable. Así que aquí viene el sujeto conductual

BehaviorSubject

Están calientes: el código se ejecuta y el valor se transmite incluso si no hay observador.

Datos compartidos: se comparten los mismos datos entre todos los observadores.

bidireccional: el observador puede asignar valor a observable (origen / maestro). más

Reproduzca el flujo de mensajes: no importa cuándo se suscriba el asunto de reproducción, recibirá todos los mensajes emitidos.

Puede establecer el valor inicial: puede inicializar el observable con el valor predeterminado.


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