如何知道switchMap是否取消订阅了内部Observable?

时间:2019-01-11 15:39:38

标签: rxjs observable rxjs6 reactivex switchmap

由于switchMap可能会切断(取消订阅)一个内部Observable(如果有新项),因此我们期望以下情况:

  const items = from([1, 2])
  const seen = []
  const derived = items.pipe(
    switchMap(item =>
      concat(
        of(`now: ${item}`),
        of(`end: ${item}`).pipe(delay(10))
      )
    )
  )

  derived.subscribe(next => seen.push(next))

导致seen具有:

['now: 1', 'now: 2', 'end: 2']
           ^ unsubscribed to 1 here, as planned!

问题是,是否有办法通知项目1被取消?原因是,如果取消发生得太频繁,我想知道。

我已经尝试了修改内部Observable的方法,但是基本上,我尝试在它们的“结尾”做的任何事情在取消订阅时根本不会发生。观察者规范包含nextcompletederror,但是“早结束”一无所获,所以我不确定该怎么做。

我希望能够将一个附加函数传递给switchMap,当内部可观察项被取消并提供参数时,该函数将由操作员调用。

  const derived = items.pipe(
    switchMap(item => concat(
      of(`now: ${item}`),
      of(`end: ${item}`).pipe(delay(10))
    ),
    (item) => console.error(`${item} was cut off.`))
  )

1 个答案:

答案 0 :(得分:1)

编辑:RxJS GitHub页面上存在一个问题,为finalize运算符讨论了此功能。 https://github.com/ReactiveX/rxjs/issues/2823

由于switchMap取消订阅内部Observable,因此不会收到任何完整的通知。

相反,您可以只添加一个处理程序,或者简单地说使用finalize()运算符为您执行此操作,并在处理链时调用它。这既涉及完成事件,也包括取消订阅事件。

switchMap(item =>
  concat(
    of(`now: ${item}`),
    of(`end: ${item}`).pipe(delay(10))
  ).pipe(
    finalize(() => /* switchMap unsubscribed or concat completed */),
  )
)

请注意,取消订阅意味着您不想再收到来自Observable的任何项目。这意味着在取消订阅时,您将无法从未订阅的Observable接收任何新项目。例如,defaultIfEmpty运算符会在源完成时发出一个项目,而不会发出任何可用于完整通知的内容,但不能正常工作而只是取消订阅。