javascript - Varför fungerar inte rxjs share-operatorn som förväntat i detta setTimeout()-exempel?
Jag förstår inte varför rxjs share-operatören inte fungerar med setTimeout().
Jag försöker förstå det här blogginlägget. I det här exemplet verkar konceptet "delad prenumeration" inte fungera som förväntat.
const observable1 = Observable.create(observer => {
observer.next(`I am alive.`);
setTimeout(() => {
observer.next(`I am alive again.`);
}, 1000);
}).pipe(share());
observable1.subscribe(x => console.log(x));
observable1.subscribe(x => console.log(x));
Förväntad :
I am alive.
I am alive again.
Faktisk :
I am alive.
I am alive again.
I am alive again.
Reproducerbar stackblitz.
Svar #1
Det är den förväntade utdata.
Från officiella dokument om share()-operatorn:
Returnerar en ny Observable som multicastar (delar) den ursprungliga Observablen. Så länge det finns minst en prenumerant kommer denna Observable att vara prenumererad och sända data.
Det betyder att så snart en observatör prenumererar börjar det observerbara sända data.
Så när det första subscribe-uttrycket observable1.subscribe(x => console.log(x)); körs, prenumererar en observatör och data skickas ut av observer.next('I am alive.');-uttrycket.
När den andra subscribe-satsen körs, prenumererar en annan observatör och den tar emot endast de data som sänds från den tidpunkten. Detta är de data som sänds av observer.next('I am alive again.'); i setTimeout()-metoden.
Vi kan se detta tydligt i den här StackBlitz-demonstrationen där vi loggar Observer1 och Observer2 text tillsammans med de mottagna uppgifterna.
Jag tror att förvirringen uppstår när man ser två I am alive again. uttalanden. Det loggas två gånger eftersom vi loggar det i varje abonnent. Flytta dessa logguttryck till observabeln och de kommer bara att loggas en gång. Detta gör det tydligare att observabeln endast körs en gång.
Svar #2
Detta är det påstådda beteendet hos share(). Det övervakar och delar endast en handling. Här är ett exempel hämtat från learnrxjs.com. Som du kan se övervakas endast tap()-operatorn. mapTo()-operatorn ignoreras.
// RxJS v6+
import { timer } from 'rxjs';
import { tap, mapTo, share } from 'rxjs/operators';
//emit value in 1s
const source = timer(1000);
//log side effect, emit result
const example = source.pipe(
tap(() => console.log('***SIDE EFFECT***')),
mapTo('***RESULT***')
);
/*
***NOT SHARED, SIDE EFFECT WILL BE EXECUTED
TWICE***
output:
"***SIDE EFFECT***"
"***RESULT***"
"***SIDE EFFECT***"
"***RESULT***"
*/
const subscribe = example.subscribe(val => console.log(val));
const subscribeTwo = example.subscribe(val => console.log(val));
//share observable among subscribers
const sharedExample = example.pipe(share());
/*
***SHARED, SIDE EFFECT EXECUTED ONCE***
output:
"***SIDE EFFECT***"
"***RESULT***"
"***RESULT***"
*/
const subscribeThree = sharedExample.subscribe(val => console.log(val));
const subscribeFour = sharedExample.subscribe(val => console.log(val));
