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.