首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RxJS:延迟的内部可观察对象仍然运行,即使外部可观察对象没有剩余的订阅

RxJS:延迟的内部可观察对象仍然运行,即使外部可观察对象没有剩余的订阅
EN

Stack Overflow用户
提问于 2018-08-17 00:06:24
回答 1查看 848关注 0票数 2

我刚刚意识到,内部可观察对象(就像在mergeMap或switchMap操作符中定义的那些)即使外部可观察对象没有剩余的订阅,也不会“停止”。

为了获得更好的示例,让我们展示一些代码:

代码语言:javascript
复制
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

由于外部观察值已经被称为finalize,因此记录side-effect 3行的事实很奇怪。

因为所有这些副作用都在defer中,所以在取消订阅后,它们可以完美地避免。在我看来,这些副作用根本没有价值。

知道为什么RxJS还在执行这些代码吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-17 01:52:29

不幸的是,这是设计上的(从RxJS 6开始)- concat将缓冲可观察对象,并将订阅每个缓冲的对象,即使在您取消订阅之后(如果订阅是closed,它将订阅并立即取消订阅)。

你必须防止可观察到的东西被缓冲...

代码语言:javascript
复制
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"); },
);

人们可能会认为上面的代码是有效的,但直到你延迟了其中一个可观察到的代码。用timer(100).pipe(mapTo(1));替换obsOf(1)和行为完全相同。

唯一的解决办法是确保您没有缓冲任何内容(意思是不使用concat*操作符),或者以其他方式限制可观察到的生产(使用单独的主体并手动控制生产)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51881243

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档