Подписка на подписку в Angular rxjs
У меня есть:
getSth(): void {
this.service.functionName.pipe(
takeUntil(this.destroy$),
distinctUntilChanged(),
map(res => res.event)
).subscribe(((response) => {
this.getAnother(response);
})); }
getAnother(response): void {
this.anotherService.anotherFunctionName(response).subscribe((res) => {
this.result = res;
}); }
Я знаю, что писать «подписаться» в «subscribe» - плохое решение. Как это исправить?
3 ответа
Воспользуемся switchMap :
getSth(): void {
this.service.functionName.pipe(
takeUntil(this.destroy$),
distinctUntilChanged(),
map(res => res.event),
switchMap(response =>
this.anotherService.anotherFunctionName(response)
)
).subscribe(response => this.result = response);
}
Вы должны стремиться связать наблюдаемые вместе, где это возможно, только с одним подписчиком на верхнем уровне. Для этого есть много веских причин, выходящих за рамки этого ответа.
Вы можете реорганизовать свой код, чтобы вернуть наблюдаемое из вашей функции (используя
tap
для выполнения любых побочных эффектов, таких как состояние обновления), и используйте
switchMap
связать его с существующим наблюдаемым.
getSth(): void {
this.service.functionName.pipe(
takeUntil(this.destroy$),
distinctUntilChanged(),
map(res => res.event),
switchMap(response => this.getAnother(response))
).subscribe();
}
// TODO: return correct type in Observable<T>
getAnother(response): Observable<any> {
return this.anotherService.anotherFunctionName(response).pipe(
tap(res => this.result = res)
);
}
У вас есть еще варианты, есть некоторые
*map
операторы, которые по-разному обрабатывают поток. В вашем примере вы можете использовать switchMap, который отменяет ваш запущенный наблюдаемый (в вашем примере
getAnother
). В документации есть дерево решений оператора , попробуйте, оно может очень помочь.
Ты получаешь
switchMap
с такой логикой:
- У меня есть один существующий Observable, и
- Я хочу создать новый Observable для каждого значения
- и отменить предыдущий вложенный Observable при поступлении нового значения
- где вложенный Observable вычисляется для каждого значения
Еще одно замечание, у вас должен быть takeUntil
быть помещенным последним.
Вы могли бы написать что-то вроде этого:
getSth(): void {
this.service.functionName.pipe(
// If service.functionName returns a new object every time distinctUntilChanged will do nothing as references won't be the same.
// distinctUntilChanged(),
switchMap(resp => this.anotherService.anotherFunctionName(resp.event))
takeUntil(this.destroy$),
).subscribe((result) => {
this.result = result;
}));
}