简体   繁体   中英

“Unsubscribe” function callback/hook in Observable “executor” function

I am confused about what the purpose of the "dispose" or "unsubscribe" function is for, which is (optionally) returned from an observable "executor" function, like so:

const Rx = require('rxjs');

const obs = Rx.Observable.create(obs => {

    // we are in the Observable "executor" function
    obs.next(4);

     // we return this function, which gets called if we unsubscribe
    return function () {
        console.log('disposed');
    }

});

    const s1 = obs.subscribe(
        function (v) {
            console.log(v);
        },
        function (e) {
            console.log(e);
        },
        function () {
            console.log('complete');
        }
    );

    const s2 = obs.subscribe(
        function (v) {
            console.log(v);
        },
        function (e) {
            console.log(e);
        },
        function () {
            console.log('complete');
        }
    );


    s1.unsubscribe();
    s2.unsubscribe();

What confuses me is that such a function would actually be more likely to hold on to references in your code and therefore prevent garbage collection.

Can anyone tell me what the purpose is of returning a function in that scenario, what the function is called, and what it's signature is? I am having trouble figuring out information about it.

I also see much more complex examples of returning a subscription from the executor function, for example this:

    let index = 0;

    let obsEnqueue = this.obsEnqueue = new Rx.Subject();

    this.queueStream = Rx.Observable.create(obs => {

        const push = Rx.Subscriber.create(v => {
            if ((index % obsEnqueue.observers.length) === obsEnqueue.observers.indexOf(push)) {
                obs.next(v);
            }
        });

        return obsEnqueue.subscribe(push);
    });

This seems to return a subscription instead of just a plain function. Can anyone explain what's going on with this?

To make it a clear question, what is the difference between doing this:

const sub = new Rx.Subject();

const obs = Rx.Observable.create($obs => {

    $obs.next(4);
    return sub.subscribe($obs);

});

and not returning the result of the subscribe call:

const sub = new Rx.Subject();

const obs = Rx.Observable.create($obs => {

    $obs.next(4);
    sub.subscribe($obs);

});

The unsubscribe function that Rx.Observable.create needs to return is invoked when downstream does not listen to the stream anymore, effectively giving you time to clean up resources.

In regards to your question; .subscribe() returns the subscription on which you can call .unsubscribe() . So if you want to do something with an other subscription you can pipe through that subscription to your downstream:

  const obs = Rx.Observable.create($obs => { const timer = Rx.Observable.interval(300) .do(i => console.log('emission: ' + i)) return timer.subscribe($obs); }); obs.take(4).subscribe(i => console.log('outer-emission:'+i)) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.2/Rx.js"></script> 

Without the unsubscribe function you would stop listening to the observable but the interval created internally would keep on running:

 const obs = Rx.Observable.create($obs => { const timer = Rx.Observable.interval(300) .do(i => console.log('emission: ' + i)) .take(10) .subscribe( val => $obs.next(val), err => $obs.error(err), () => $obs.complete() ); return function(){} // empty unsubscribe function, internal subscription will keep on running }); obs.take(4).subscribe(i => console.log('outer-emission:'+i)) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.2/Rx.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM