RxJS Observable: выполнение очистки при удалении последней подписки?

Каков самый простой способ выполнить побочный эффект при удалении последней подписки для RxJS Observable? Это может произойти до завершения работы Observable.

Допустим, мне нужна функция, возвращающая Observable, которая передает изменения в ресурс. Я хочу выполнить очистку после удаления всех подписок.

var observable = streamResourceChanges(resource);
var subscription1 = observable.subscribe(observer1);
var subscription2 = observable.subscribe(observer2);
// ...
subscription1.dispose();  // Does not perform the cleanup
subscription2.dispose();  // Performs the cleanup

Единственный найденный мной способ определить действие удаления подписки — использовать Rx.Observable.create. Последнее удаление можно выполнить, поделившись подпиской, например, с Observable.prototype.singleInstance().

Например:

function streamResourceChanges(resource) {
    return Rx.Observable.create(function(observer) {
        // Subscribe the observer for resource changes...
        // Return a cleanup function
        return function() {
            // Perform cleanup here...
            console.log("Cleanup performed!");
        };
    }).singleInstance();
}

Есть ли более аккуратный способ определить побочный эффект для удаления подписки, подобный doOnNext, doOnCompleted или doOnError?

var withCleanup = withoutCleanup.doOnDispose(function() {
    // Perform cleanup here...
});

person Kimmo    schedule 26.10.2015    source источник


Ответы (1)


В зависимости от вашего фактического варианта использования на ум приходят два варианта:

.finally()

source.finally(() => console.log("cleaning up")).singleInstance()

.using()

Rx.Observable
    .using(
        // allocate some disposable resource during subscribe.
        // resource.dispose() will be called during unsubscribe.
        () => new SomeResource(),

        // use the disposable resource to create your observable
        // for example...
        resource => Rx.Observable.interval(resource.time))
    .singleInstance();
person Brandon    schedule 26.10.2015
comment
Спасибо! Метод using звучит как достойная альтернатива create! Обратный вызов finally запускается только тогда, когда Observable завершается, что может не обязательно иметь место при удалении последней подписки. Извините, я не очень конкретно об этом; Я отредактировал свой вопрос. - person Kimmo; 27.10.2015
comment
В документации это не очень хорошо указано. Наконец, фактически вызывает действие при удалении подписки, в том числе при завершении или при удалении подписки вручную. - person Brandon; 27.10.2015
comment
Я попробовал finally, и вы совершенно правы! В документации на данный момент ничего не говорится об этом поведении (а также неверное описание параметра обратного вызова). Итак, это именно то, что я искал! Благодарю вас! - person Kimmo; 27.10.2015
comment
.finally() был переименован в конвейерный finalize() - person biolauri; 26.02.2019