web-dev-qa-db-ja.com

RxJSObservablesから退会する

私はこれらの2つのオブジェクトを持っているので、それらのイベントを聞くのをやめたいと思います。私はobservablesとRxJSにまったく慣れておらず、 Inquirer ライブラリを操作しようとしています。

参考のためにRxJSAPIを次に示します。 http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html

これらのタイプのオブザーバブルの購読を解除するにはどうすればよいですか?

ConnectableObservable:

   ConnectableObservable {
     source: EventPatternObservable { _add: [Function], _del: [Function], _fn: undefined },
     _connection: ConnectDisposable { _p: [Circular], _s: [Object] },
     _source: AnonymousObservable { source: [Object], __subscribe: [Function: subscribe] },
     _subject: 
      Subject {
        isDisposed: false,
        isStopped: false,
        observers: [Object],
        hasError: false } },
  _count: 1,
  _connectableSubscription: 
   ConnectDisposable {
     _p: 
      ConnectableObservable {
        source: [Object],
        _connection: [Circular],
        _source: [Object],
        _subject: [Object] },
     _s: AutoDetachObserver { isStopped: false, observer: [Object], m: [Object] } } }

FilterObservable:

FilterObservable {
  source: 
   RefCountObservable {
     source: 
      ConnectableObservable {
        source: [Object],
        _connection: [Object],
        _source: [Object],
        _subject: [Object] },
     _count: 1,
     _connectableSubscription: ConnectDisposable { _p: [Object], _s: [Object] } },
  predicate: [Function] }

これらのオブジェクトの購読を解除する必要があります。

'use strict';
var rx = require('rx');

function normalizeKeypressEvents(value, key) {
  return {value: value, key: key || {}};
}

module.exports = function (rl) {

  var keypress = rx.Observable.fromEvent(rl.input, 'keypress', normalizeKeypressEvents)
    .filter(function (e) {
      // Ignore `enter` key. On the readline, we only care about the `line` event.
      return e.key.name !== 'enter' && e.key.name !== 'return';
    });

  return {
    line: rx.Observable.fromEvent(rl, 'line'),

    keypress: keypress,

    normalizedLeftKey: keypress.filter(function (e) {
      return e.key.name === 'left';
    }).share(),

    normalizedRightKey: keypress.filter(function (e) {
      return e.key.name === 'right';
    }).share(),

    normalizedUpKey: keypress.filter(function (e) {
      return e.key.name === 'up' || e.key.name === 'k' || (e.key.name === 'p' && e.key.ctrl);
    }).share(),

    normalizedDownKey: keypress.filter(function (e) {
      return e.key.name === 'down' || e.key.name === 'j' || (e.key.name === 'n' && e.key.ctrl);
    }).share(),

    numberKey: keypress.filter(function (e) {
      return e.value && '123456789'.indexOf(e.value) >= 0;
    }).map(function (e) {
      return Number(e.value);
    }).share(),

    spaceKey: keypress.filter(function (e) {
      return e.key && e.key.name === 'space';
    }).share(),

    aKey: keypress.filter(function (e) {
      return e.key && e.key.name === 'a';
    }).share(),

    iKey: keypress.filter(function (e) {
      return e.key && e.key.name === 'i';
    }).share()
  };
};

私の現在の最善の推測は、次のような明示的なサブスクライブの呼び出しは行われていないということです。

var source = Rx.Observable.fromEvent(input, 'click');

var subscription = source.subscribe(
  function (x) {
    console.log('Next: Clicked!');
  },
  function (err) {
    console.log('Error: %s', err);
  },
  function () {
    console.log('Completed');
  });

しかし、代わりに、次の呼び出しがあります。

events.normalizedUpKey.takeUntil(validation.success).forEach(this.onUpKey.bind(this));
events.normalizedDownKey.takeUntil(validation.success).forEach(this.onDownKey.bind(this));

したがって、私の最善の推測は、takeUntil呼び出しを無効化/キャンセルする方法が必要だということです。

7
Alexander Mills

登録を解除する場合は、 Subscription オブジェクトが必要です。これは、すべてのObservable.subscribe()呼び出しから返されるオブジェクトです。例えば:

let subscriber = Observable.subscribe(...);
...
subscriber.unsubscribe();

詳細については、以下を参照してください: https://github.com/ReactiveX/rxjs/blob/master/doc/subscription.md

16
martin

私は最初のコメンターが言っていたことを2番目にしています。ただし、コードのどこかに次のような呼び出しが必要であると感じています。

let subscription = normalizedUpKey.subscribe( data => console.log('data') );

あなたができること

subscription.unsubscribe()

オン。何かが起こったときに他にどのように知っていますか、それともサードパーティのライブラリの一部ですか?

Rxjsの詳細を読む。この無料の本をご覧になることをお勧めします https://www.gitbook.com/book/chrisnoring/rxjs-5-ultimate/details

3
Chris Noring

オブザーバブルからのサブスクライブを解除する必要はなく、プロトコルもありません。実際、私はあなたの質問のコード、特に共有によって構成されたオブザーバブルの束が含まれているリターンオブジェクトの部分を見ています。ただし、これらのオブザーバブルはサブスクリプションではなくオブザーバブルであるため、これらの要素にはunsubscribingと呼ばれる概念はありません。

したがって、モジュールの外部にいくつかの新しいサブスクライブのようなコードがあり、イベントオブザーバブルを正確に処理する場合は、特定のサブスクリプションインスタンスのサブスクライブを解除できます。

現在、問題のコードの場合、ソースobservableで使用されるメソッドは、実行をサブスクライブするのではなく、.filter().share().takeUntil()などのすべての演算子です。実際には、メソッドは新しいオブザーバブルを返します。

Rxjsの公式ドキュメントで説明されているように、.share()multicasted observables を作成しますが、便利なものを使用すると、サブスクライバーの数が1から0に減少すると実行が停止する可能性があります。コード内の.share()も正確に含まれている演算子。

結論として、質問のコードのサブスクライブを解除するイベントについて心配する必要はありません。潜在的に、あなたの質問で説明されている懸念のように聞こえるさらなる問題が実際にあります:.connect()の代わりに.share()を使用する場合。これは、 ConnectableObservable についての状況であり、イベントバインディングを手動でキャンセルすることを懸念する必要があります。

1
千木郷