RxJS:外部オブザーバブルにサブスクリプションが残っていない場合でも、遅延された内部オブザーバブルは実行されます

DonCorneo

内側のオブザーバブル(mergeMapまたはswitchMapオペレーターで定義されているものなど)は、外側のオブザーバブルにサブスクリプションが残っていなくても「停止」しないことに気づきました。

より良い例として、いくつかのコードを示しましょう。

const {
  Subject,
  of: obsOf,
  concat: obsConcat,
  defer,
} = require("rxjs");
const {
  finalize,
  mergeMap,
  tap,
  takeUntil,
} = require("rxjs/operators");

const subject = new Subject();

obsOf(null).pipe(
  mergeMap(() =>
    obsConcat(
      defer(() => {
        console.log("side-effect 1");
        return obsOf(1);
      }),
      defer(() => {
        console.log("side-effect 2");
        return obsOf(2);
      }),
      defer(() => {
        console.log("side-effect 3");
        return obsOf(3);
      })
    )
  ),
  finalize(() => {
    console.log("finalized");
  })
)
.pipe(
  takeUntil(subject),
  tap((i) => {
    if (i === 2) {
      subject.next();
    }
  })
).subscribe(
  (i) => { console.log("next", i); },
  (e) => { console.log("error", e); },
  () => { console.log("complete"); },
);

// Ouput:
// > side-effect 1
// > next 1
// > side-effect 2
// > complete
// > finalized
// > side-effect 3

side-effect 3外側のオブザーバブルがすでにと呼ばれてfinalizeいるので行がログに記録されるという事実は奇妙です。

これらの副作用はすべてdeferに含まれているため、サブスクリプションを解除した後は完全に回避できます。私の観点からは、これらの副作用はまったく価値がありません。

RxJSがまだそれらを実行する理由はありますか?

m1ch4ls

残念ながら、これは設計によるものです(RxJS 6以降)-concatオブザーバブルをバッファリングし、サブスクライブを解除した後でも、バッファリングされた各オブザーバブルをサブスクライブします(サブスクリプションのclosed場合はサブスクライブしてすぐにサブスクライブを解除します)。

オブザーバブルがバッファリングされないようにする必要があります...

obsOf(null).pipe(
  mergeMap(() => obsOf(
    defer(() => {
      console.log("side-effect 1");
      return obsOf(1);
    }),
    defer(() => {
      console.log("side-effect 2");
      return obsOf(2);
    }),
    defer(() => {
      console.log("side-effect 3");
      return obsOf(3);
    })
  )),
  concatAll(),
  finalize(() => {
    console.log("finalized");
  }),
  takeUntil(subject),
  tap((i) => {
    if (i === 2) {
      subject.next();
    }
  })
).subscribe(
  (i) => { console.log("next", i); },
  (e) => { console.log("error", e); },
  () => { console.log("complete"); },
);

上記のコードは機能すると考えることができますが、オブザーバブルの1つを遅らせるまでです。元に戻しobsOf(1)timer(100).pipe(mapTo(1));や行動はまったく同じです。

唯一の回避策は、何もバッファリングしていないことを確認するか(concat*演算子を使用しないことを意味します)、または他の方法で監視可能なプロダクションを制限することです(別のサブジェクトを使用し、プロダクションを手動で制御します)。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ