Преобразование моего исходного комментария в ответ с добавленными мыслями ...
Оригинальный комментарий
Первая версия гарантирует порядок обработки. Вызов в службу не будет выполнен, пока не будет возвращен параметр маршрута.
Ваша версия запускает две подписки параллельно. Так что они не эквивалентны. Независимо от того, являются ли они функционально эквивалентными, зависит от отношений между this.heroes$
и this.selectedId
.
Если сервисный вызов зависел от параметра маршрута, вам пришлось бы использовать первый подход.
Обновление
Проверка привела к этому думать о небольшой, но важной разнице. Первая версия делает дублирующие сервисные звонки. Наблюдаемая paramMap будет срабатывать каждый раз при обновлении параметра маршрута. Ниже приведен один пример того, как это могло бы произойти.
ngOnInit(): void {
this.route.paramMap.subscribe(params => {
// this will be called every time the selectHero function is called
this.selectedId = params.get('id');
});
this.heroes$ = this.service.getHeroes();
}
// Event handler, called from the HTML
selectHero(id: string): void {
// Triggers emission of a new param value in route.paramMap
this.router.navigate(['/heroes', { id: id }]);
}
Если бы вызов службы был внутри подписки param, служба будет вызываться каждый раз. Предполагая, что герои не изменяются в базе данных в течение всего времени существования компонента, и нет кэширования на стороне приложения, тогда мы делаем избыточные вызовы.
Я читал, что switchMap возвращает подписка на Observable первого порядка, а также отменяет предыдущие подписки. Это то, что мой код не делает, и это то, о чем я должен беспокоиться / беспокоиться?
switchMap
не отменяет подписку на внешнюю наблюдаемую, она отменяет внутреннюю наблюдаемую при выдаче нового значения , Я создал простой стек-блиц для демонстрации этого.
Перейдите на страницу «прочее» и нажмите одну из ссылок «Один», «Два», «Три». Каждый щелчок обновит параметр маршрута, и вы увидите журнал, который из подписок все еще работает.
Слишком много кода для вставки, но он устанавливает следующие надписи:
const p$ = this.route.paramMap;
p$.subscribe(params => {});
p$.pipe(take(1)).subscribe(params => {});
p$.pipe(switchMap(params => of(params.get('id')))).subscribe(id => {});
p$.pipe(takeUntil(this.timerElapsed)).subscribe(params => {});
Подписки 1 и 3 будут работать в течение всего срока службы компонента. Это показывает, что наличие switchMap
в вашем первом примере не приведет к автоматической отмене подписки, если вы к этому добились.
Я также читал, что мне не нужно отписаться ActivatedRoute наблюдаемые. Это тот случай, когда мне не нужно отписываться от paramMap в моей версии ngOnInit?
Существует очень мало официальной документации по этому вопросу, которую я могу найти. Это часто повторяемое утверждение из авторитетных источников. Эта относительно недавняя статья повторяет утверждение.
Нет необходимости отписываться от активированного маршрута.
Часто утверждается, что отписаться как правило, это хорошая практика, и если вы используете канал async
(который, как я полагаю, будет иметь место в вашем примере), то в любом случае автоматически выполняется очистка подписок.
Заключение
- Приведение в порядок наблюдаемых
Нет разницы между вашими примерами. Вам не нужно убирать ActivatedRoute
подписок, и не нужно было бы убирать наблюдаемую услугу, если она от HttpClient
.
Порядок звонков
Ваш первый пример гарантирует порядок, второй - нет. Это вряд ли окажет практическое влияние, поскольку маршрутизатор почти наверняка вернет параметр, прежде чем служба вернет результат (при условии запроса XHR).
Количество сервисных вызовов
Ваш первый пример выполняет 1 сервисный вызов на смену параметра (включая начальную подписку). Ваш второй пример делает 1 сервисный вызов за время жизни компонента. Какой из них правильный, зависит от вашей стратегии кэширования и нестабильности данных.
Я еще раз рассмотрел это, потому что это более интересный вопрос, который я изначально предполагал. Я рад, что я сделал, и я призываю вас медленно исследовать мощный и запутанный мир Rx JS.