RxJS - Trabajar con sujetos

Un sujeto es un observable que puede realizar multidifusión, es decir, hablar con muchos observadores. Considere un botón con un detector de eventos, la función adjunta al evento que usa agregar detector se llama cada vez que el usuario hace clic en el botón, una funcionalidad similar también se aplica al tema.

Vamos a discutir los siguientes temas en este capítulo:

  • Crea un tema
  • ¿Cuál es la diferencia entre observable y sujeto?
  • Asunto de comportamiento
  • Asunto de repetición
  • AsyncSubject

Crea un tema

Para trabajar con el asunto, necesitamos importar el asunto como se muestra a continuación:

import { Subject } from 'rxjs';

Puede crear un objeto sujeto de la siguiente manera:

const subject_test = new Subject();

El objeto es un observador que tiene tres métodos:

  • next(v)
  • error(e)
  • complete()

Suscribirse a un tema

Puede crear múltiples suscripciones sobre el tema como se muestra a continuación:

subject_test.subscribe({
   next: (v) => console.log(`From Subject : ${v}`)
});
subject_test.subscribe({
   next: (v) => console.log(`From Subject: ${v}`)
});

La suscripción se registra en el objeto sujeto al igual que addlistener que discutimos anteriormente.

Pasando datos al sujeto

Puede pasar datos al sujeto creado utilizando el método next ().

subject_test.next("A");

Los datos se pasarán a toda la suscripción agregada sobre el tema.

Ejemplo

Aquí hay un ejemplo práctico del tema:

import { Subject } from 'rxjs';

const subject_test = new Subject();

subject_test.subscribe({
   next: (v) => console.log(`From Subject : ${v}`)
});
subject_test.subscribe({
   next: (v) => console.log(`From Subject: ${v}`)
});
subject_test.next("A");
subject_test.next("B");

El objeto subject_test se crea llamando a un nuevo Subject (). El objeto subject_test hace referencia a los métodos next (), error () y complete (). La salida del ejemplo anterior se muestra a continuación:

Salida

Podemos usar el método complete () para detener la ejecución del sujeto como se muestra a continuación.

Ejemplo

import { Subject } from 'rxjs';

const subject_test = new Subject();

subject_test.subscribe({
   next: (v) => console.log(`From Subject : ${v}`)
});
subject_test.subscribe({
   next: (v) => console.log(`From Subject: ${v}`)
});
subject_test.next("A");
subject_test.complete();
subject_test.next("B");

Una vez que llamamos a complete, no se invoca el siguiente método llamado más tarde.

Salida

Veamos ahora cómo llamar al método error ().

Ejemplo

A continuación se muestra un ejemplo de trabajo:

import { Subject } from 'rxjs';

const subject_test = new Subject();

subject_test.subscribe({
   error: (e) => console.log(`From Subject : ${e}`)
});
subject_test.subscribe({
   error: (e) => console.log(`From Subject : ${e}`)
});
subject_test.error(new Error("There is an error"));

Salida

¿Cuál es la diferencia entre observable y sujeto?

Un observable hablará uno a uno, con el suscriptor. Cada vez que se suscribe al observable, la ejecución comenzará desde cero. Tome una llamada Http realizada usando ajax y 2 suscriptores llamando al observable. Verá 2 solicitudes HttpHttp en la pestaña de red del navegador.

Ejemplo

Aquí hay un ejemplo práctico de lo mismo:

import { ajax } from 'rxjs/ajax';
import { map } from 'rxjs/operators';

let final_val = ajax('https://jsonplaceholder.typicode.com/users').pipe(map(e => e.response));
let subscriber1 = final_val.subscribe(a => console.log(a));
let subscriber2 = final_val.subscribe(a => console.log(a));

Salida

Ahora, aquí el problema es que queremos que se compartan los mismos datos, pero no, a costa de 2 llamadas Http. Queremos hacer una llamada Http y compartir los datos entre suscriptores.

Esto será posible usando Subjects. Es un observable que puede realizar multidifusión, es decir, hablar con muchos observadores. Puede compartir el valor entre suscriptores.

Ejemplo

Aquí hay un ejemplo de trabajo usando Subjects:

import { Subject } from 'rxjs';
import { ajax } from 'rxjs/ajax';
import { map } from 'rxjs/operators';

const subject_test = new Subject();

subject_test.subscribe({
   next: (v) => console.log(v)
});
subject_test.subscribe({
   next: (v) => console.log(v)
});

let final_val = ajax('https://jsonplaceholder.typicode.com/users').pipe(map(e => e.response));
let subscriber = final_val.subscribe(subject_test);

Salida

Ahora puede ver solo una llamada Http y los mismos datos se comparten entre los suscriptores llamados.

Asunto de comportamiento

El sujeto de comportamiento le dará el último valor cuando se le llame.

Puede crear un sujeto de comportamiento como se muestra a continuación:

import { BehaviorSubject } from 'rxjs';
const subject = new BehaviorSubject("Testing Behaviour Subject"); 
// initialized the behaviour subject with value:Testing Behaviour Subject

Ejemplo

Aquí hay un ejemplo práctico para usar Behavior Subject:

import { BehaviorSubject } from 'rxjs';
const behavior_subject = new BehaviorSubject("Testing Behaviour Subject"); 
// 0 is the initial value

behavior_subject.subscribe({
   next: (v) => console.log(`observerA: ${v}`)
});

behavior_subject.next("Hello");
behavior_subject.subscribe({
   next: (v) => console.log(`observerB: ${v}`)
});
behavior_subject.next("Last call to Behaviour Subject");

Salida

Asunto de repetición

Un tema de reproducción es similar al sujeto de comportamiento, en el que puede almacenar los valores en búfer y reproducir los mismos para los nuevos suscriptores.

Ejemplo

Aquí hay un ejemplo práctico de sujeto de repetición:

import { ReplaySubject } from 'rxjs';
const replay_subject = new ReplaySubject(2); 
// buffer 2 values but new subscribers

replay_subject.subscribe({
   next: (v) => console.log(`Testing Replay Subject A: ${v}`)
});

replay_subject.next(1);
replay_subject.next(2);
replay_subject.next(3);
replay_subject.subscribe({
   next: (v) => console.log(`Testing Replay Subject B: ${v}`)
});

replay_subject.next(5);

El valor de búfer utilizado es 2 en el sujeto de la repetición. Por lo tanto, los dos últimos valores se almacenarán en búfer y se usarán para los nuevos suscriptores llamados.

Salida

AsyncSubject

En el caso de AsyncSubject, el último valor llamado se pasa al suscriptor y se hará solo después de que se llame al método complete ().

Ejemplo

Aquí hay un ejemplo práctico de lo mismo:

import { AsyncSubject } from 'rxjs';

const async_subject = new AsyncSubject();

async_subject.subscribe({
   next: (v) => console.log(`Testing Async Subject A: ${v}`)
});

async_subject.next(1);
async_subject.next(2);
async_subject.complete();
async_subject.subscribe({
   next: (v) => console.log(`Testing Async Subject B: ${v}`)
});

Aquí, antes de que se llame completo, el último valor que se le pasa al sujeto es 2 y el mismo que se le da a los suscriptores.

Salida