How does the RxJs 5 share() operator work?

后端 未结 2 842
野性不改
野性不改 2020-12-10 10:05

Its not 100% clear for me how the RxJs 5 share() operator works, see here the latest docs. Jsbin for the question here.

If I create an observable with a

相关标签:
2条回答
  • 2020-12-10 10:58

    Be careful that you are using RxJS v5 while your documentation link seem to be RxJS v4. I don't remember specifics but I think that the share operator went through some changes, in particular when it comes to completion and resubscription, but don't take my word for it.

    Back to your question, as you have shown in your study, your expectations do not correspond to the library design. Observables lazily instantiate their data flow, concretely initiating the dataflow when a subscriber subscribes. When a second subscriber subscribes to the same observable, another new dataflow is started as if it is was the first subscriber (so yes, each subscription creates a new chain of observables as you said). This is what is coined in RxJS terminology as a cold observable and that's the default behaviour for RxJS observable. If you want an observable which sends its data to the subscribers it has at the moment the data arrives, this is coined a hot observable, and one way to get a hot observable is to use the share operator.

    You can find illustrated subscription and data flows here : Hot and Cold observables : are there 'hot' and 'cold' operators? (this is valid for RxJS v4, but most of it is valid for v5).

    0 讨论(0)
  • 2020-12-10 10:59

    share makes the observable "hot" if these 2 conditions are met:

    1. the number of subscribers > 0
    2. AND the observable has not completed

    Scenario1: number of subscribers > 0 and observable is not completed before a new subscription

    var shared  = rx.Observable.interval(5000).take(2).share();
    var startTime = Date.now();
    var log = (x) => (value) => { 
        console.log(`onNext for ${x}, Delay: ${Date.now() - startTime} , Value: ${value}`);
    };
    
    var observer1 = shared.subscribe(log('observer1')),
        observer2;
    
    setTimeout(()=>{
        observer2 = shared.subscribe(log('observer2'));
    }, 3000);
    
    // emission for both observer 1 and observer 2, with the samve value at startTime + 5 seconds
    // another emission for both observers at: startTime + 10 seconds
    

    Scenario 2: number of subscribers is zero before a new subscription. Becomes "cold"

     var shared  = rx.Observable.interval(5000).take(2).share();
        var startTime = Date.now();
        var log = (x) => (value) => { 
        console.log(`onNext for ${x}, Delay: ${Date.now() - startTime} , Value: ${value}`);
    };
    
    var observer1 = shared.subscribe(log('observer1')),
        observer2;
    
    setTimeout(()=>{
        observer1.unsubscribe(); 
    }, 1000);
    
    setTimeout(()=>{
        observer2 = shared.subscribe(log('observer2')); // number of subscribers is 0 at this time
    }, 3000);
    // observer2's onNext is called at startTime + 8 seconds
    // observer2's onNext is called at startTime + 13 seconds
    

    Scenario 3: when observable was completed before a new subscription. Becomes "cold"

     var shared  = rx.Observable.interval(5000).take(2).share();
        var startTime = Date.now();
        var log = (x) => (value) => { 
            console.log(`onNext for ${x}, Delay: ${Date.now() - startTime} , Value: ${value}`);
        };
    
    var observer1 = shared.subscribe(log('observer1')),
        observer2;
    
    setTimeout(()=>{
        observer2 = shared.subscribe(log('observer2'));
    }, 12000);
    
    // 2 emission for observable 1, at startTime + 5 secs, and at startTime + 10secs
    // 2 emissions for observable 2,at startTime + 12 + 5 secs, and at startTime + 12 + 10secs
    
    0 讨论(0)
提交回复
热议问题