RxJS - Lavorare con i soggetti
Un soggetto è un osservabile che può trasmettere in multicast, ovvero parlare con molti osservatori. Si consideri un pulsante con un listener di eventi, la funzione allegata all'evento utilizzando add listener viene chiamata ogni volta che l'utente fa clic sul pulsante, funzionalità simili valgono anche per l'oggetto.
Discuteremo i seguenti argomenti in questo capitolo:
- Crea un soggetto
- Qual è la differenza tra osservabile e soggetto?
- Oggetto del comportamento
- Ripeti oggetto
- AsyncSubject
Crea un soggetto
Per lavorare con l'oggetto, dobbiamo importare l'oggetto come mostrato di seguito:
import { Subject } from 'rxjs';
È possibile creare un oggetto soggetto come segue:
const subject_test = new Subject();
L'oggetto è un osservatore che ha tre metodi:
- next(v)
- error(e)
- complete()
Iscriviti a un argomento
È possibile creare più abbonamenti sull'argomento come mostrato di seguito:
subject_test.subscribe({
next: (v) => console.log(`From Subject : ${v}`)
});
subject_test.subscribe({
next: (v) => console.log(`From Subject: ${v}`)
});
La sottoscrizione viene registrata nell'oggetto soggetto proprio come addlistener di cui abbiamo discusso in precedenza.
Passaggio di dati al soggetto
È possibile passare i dati all'oggetto creato utilizzando il metodo next ().
subject_test.next("A");
I dati verranno passati a tutti gli abbonamenti aggiunti sull'argomento.
Esempio
Ecco un esempio funzionante dell'argomento:
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");
L'oggetto subject_test viene creato chiamando un nuovo Subject (). L'oggetto subject_test fa riferimento ai metodi next (), error () e complete (). L'output dell'esempio precedente è mostrato di seguito:
Produzione
Possiamo usare il metodo complete () per interrompere l'esecuzione del soggetto come mostrato di seguito.
Esempio
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 volta chiamato complete, il metodo successivo chiamato in seguito non viene richiamato.
Produzione
Vediamo ora come chiamare il metodo error ().
Esempio
Di seguito è riportato un esempio funzionante:
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"));
Produzione
Qual è la differenza tra osservabile e soggetto?
Un osservabile parlerà uno a uno, con l'abbonato. Ogni volta che ti iscrivi all'osservabile l'esecuzione inizierà da zero. Rispondi a una chiamata HTTP effettuata utilizzando ajax e 2 abbonati chiamano l'osservabile. Vedrai 2 richieste HttpHttp nella scheda di rete del browser.
Esempio
Ecco un esempio funzionante dello stesso:
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));
Produzione
Ora, qui il problema è che vogliamo condividere gli stessi dati, ma non al costo di 2 chiamate Http. Vogliamo fare una chiamata Http e condividere i dati tra gli abbonati.
Ciò sarà possibile utilizzando i Soggetti. È un osservabile che può trasmettere in multicast, ovvero parlare con molti osservatori. Può condividere il valore tra gli abbonati.
Esempio
Ecco un esempio funzionante che utilizza Soggetti:
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);
Produzione
Ora puoi vedere solo una chiamata Http e gli stessi dati sono condivisi tra gli abbonati chiamati.
Oggetto del comportamento
L'oggetto del comportamento ti darà l'ultimo valore quando viene chiamato.
Puoi creare un soggetto comportamentale come mostrato di seguito:
import { BehaviorSubject } from 'rxjs';
const subject = new BehaviorSubject("Testing Behaviour Subject");
// initialized the behaviour subject with value:Testing Behaviour Subject
Esempio
Ecco un esempio funzionante per utilizzare 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");
Produzione
Ripeti oggetto
Un replaysubject è simile al behavior subject, in cui può bufferizzare i valori e riprodurre lo stesso ai nuovi abbonati.
Esempio
Ecco un esempio funzionante di soggetto replay:
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);
Il valore del buffer utilizzato è 2 sull'oggetto della riproduzione. Quindi gli ultimi due valori verranno memorizzati nel buffer e utilizzati per i nuovi abbonati chiamati.
Produzione
AsyncSubject
Nel caso di AsyncSubject, l'ultimo valore chiamato viene passato al sottoscrittore e verrà eseguito solo dopo che il metodo complete () è stato chiamato.
Esempio
Ecco un esempio funzionante dello stesso:
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}`)
});
Qui, prima che venga chiamato complete, l'ultimo valore passato al soggetto è 2 e lo stesso dato agli iscritti.