Как узнать, если switchMap отписался от внутреннего Observable? - PullRequest
0 голосов
/ 11 января 2019

Поскольку switchMap может отрезать (отписаться) внутреннюю наблюдаемую часть, если появится новый элемент, мы ожидаем следующее:

  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? Причина в том, что если отмены происходят слишком часто, я бы хотел знать.

Я пробовал способы изменения внутренних Observables, но в основном все, что я пытаюсь сделать «в конце», просто не происходит, когда отписывается. Спецификация Observer имеет next, completed и error, но ничего не значит "рано закончился", поэтому я не уверен, что попробовать.

Я бы хотел иметь возможность передать дополнительную функцию в 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 голосов
/ 11 января 2019

Редактировать: На странице 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 при отписке. Например, есть оператор defaultIfEmpty, который испускает элемент при завершении источника, не выдавая ничего, что работает для полных уведомлений, но не может работать, вы просто отменили подписку.

...