Отказ от подписки на ReplaySubject, возвращаемый asObservable (); - PullRequest
0 голосов
/ 03 сентября 2018

Заголовок

Если у вас, по сути, один и тот же вопрос, и у вас контекст Angular, вы можете прочитать все комментарии в ответе для получения дополнительной информации.

Краткая версия этого вопроса

При выполнении let observe$ = someReplaySubject.asObservable() мы больше не обязаны отписываться от observe$? Другими словами, можем ли мы вызвать let observe$ = someReplaySubject.asObservable() из нескольких экземпляров Angular-компонента и не беспокоиться о соединении между экземпляром notify и соответствующим Observable?

Предположения

Если у нас есть экземпляр ReplaySubject<Todo[]> (давайте назовем его rxTodo, и мы подпишемся на него из компонентов Angular, выполнив:

let todoObs$:Observable<Todo[]> = rxTodo$.asObservable() тогда, даже если компонент уничтожен, ссылки todoObs$, созданные в каждом компоненте, будут свисать, пока сам компонент не будет уничтожен.

Фон

Я пытаюсь Store API для Angular, и у меня есть тема воспроизведения, которая передает изменения в срезы магазина. Вот метод, который позволяет подпискам происходить (notifyCount отслеживает подписки, поэтому, если их нет, мы не беспокоимся об уведомлении):

<code>  /**
   * Subscribe to receive slice updates.
   * @example
     <pre>
    let todos$ = slice.subscribe();
    
* / public subscribe (): Observable { this.notifyCount ++; вернуть this.notify.asObservable (); }

Выше я пытаюсь следовать рекомендуемой наилучшей практике возврата Observable вместо ReplaySubject.

Это соответствующий unsubscribe метод:

<code>  /**
   * Unsubscribe from slice updates.
   * 
   * @example 
    <pre>
      slice.unsubscribe(o);
    
* / публичная отмена подписки (o: ReplaySubject ) { o.unsubscribe (); this.notifyCount--; }

Мне пришлось сделать аргумент o типа ReplaySubject, чтобы unsubscribe. Однако это противоречит типу Observable, который возвращает метод subscribe.

При попытке выполнить тестирование следующим образом:

incompleteSlice.unsubscribe(incomplete$);

Возвращаемое сообщение:

[ц] Аргумент типа 'Observable' не может быть назначен параметру типа 'ReplaySubject'. Свойство scheduler отсутствует в типе Observable. пусть неполное $: наблюдаемый

Есть мысли, как это исправить?

Обновление

Одна очевидная мысль, которая только что пришла в голову, заключается в том, что, возможно, возвращение asObservable означает, что нам больше не нужно на самом деле unsubscribe из этой наблюдаемой. Мы можем просто оставить его болтаться в случае разрушения компонента Angular?

1 Ответ

0 голосов
/ 03 сентября 2018

Я думаю, что вы путаете отписку от Subscription и от Subject.

Что действительно рекомендуется в Angular, так это отписываться от любого открытого Subscription, когда компонент уничтожается. Subscription возвращается из Observable.subscribe. Когда он отписывается, он больше не получает значения из наблюдаемого источника, что вам и нужно в большинстве случаев.

Отмена подписки на Subject имеет другой эффект. Он переключает субъект в состояние closed, где вы больше не можете звонить next или подписаться на него. Вы можете посмотреть прямо на исходный код , чтобы понять, что происходит.

Отмена подписки на Observable невозможна, отчасти поэтому вы получаете ошибку.

Чтобы выполнить рекомендацию, вы должны либо составить список всех подписок , то есть добавить каждую подписку в список, к которому вы сможете получить доступ позже, например:

this.subscriptions$.push(obs$.subscribe...))

А затем при уничтожении компонента вызовите:

this.subscriptions$.forEach(sub -> sub.unsubscribe());

Но даже лучше и , рекомендованный разработчиком ядра Беном Лешем в этой статье, не обязательно вызывает unsubscribe, а вместо этого использует оператор takeUntil.

В StackOverflow существует эталонная реализация для использования этого шаблона с Angular, которую можно использовать в качестве отправной точки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...