Я закодировал две наблюдаемые:
Один для захвата событий отправки формы:
<form role = "form" (ngSubmit) = "search()">
...
</form>
И search()
достигается и излучает:
private search(): void {
this.searchClickSubject.next();
}
В конструкторе компонентов:
private searchClickSubject:Subject<void>;
private searchClick$:Observable<any>;
constructor() {
this.searchClickSubject = new Subject<void>();
this.searchClick$ = this.searchClickSubject.asObservable();
}
Как видите, я создаю Observable
из темы searchClickSubject
, используя метод searchClickSubject.asObservable
для searchClick$
.
С этого момента я использую этот searchClick$
Observable, чтобы ловить submit form
.
После этого я создаю еще один Observable:
this.searchQuery$ = this.searchClick$.pipe(
map(() => <Query>{
offset: 0,
limit: 10
})
);
Итак, каждый раз, когда выдается Query
, я делаю запрос с использованием пользовательских функций конвейера:
this.metrics$ = this.searchQuery$
.pipe(
pageLoading(),
makeRequest(),
loadedPage()
);
Это мой ngOnInit()
:
public ngOnInit() {
// Grab search button click event
this.searchQuery$ = this.searchClick$.pipe(
map(() => <Query>{
offset: 0,
limit: 10
})
);
this.metrics$ = this.searchQuery$
.pipe(
//...
);
}
Однако запрос запускается дважды.
Я создаю подписки с помощью конвейера async
:
<div class = "row" *ngIf = "!(metrics$ | async)" style = "margin: 1.54em;">
<div *ngIf = "metrics$ | async; let metric;"...
Есть идеи?
Вы подписываетесь на наблюдаемый metrics$
два раза. Вот что происходит:
*ngIf = "!(metrics$ | async)"
.*ngIf = "metrics$ | async; let metric;"
.Используйте оператор share()
в metrics$
, чтобы предотвратить повторный запрос на новую подписку. Если вы хотите глубже понять эту тему, ознакомьтесь с этим отличная статья.
Почему вы говорите, что я использую BehaviorSubject
? Насколько мне удалось выяснить, я использую Subject<void>
в качестве исходного источника, чтобы поймать отправку формы... С другой стороны... А как насчет ReplaySubject
? Я думаю, что не стоит делиться и http-запросом...
Итак, я имею в виду, что оператор share()
— это хороший обходной путь, но я думаю, что он пахнет таким «обходным решением». По ot и cold вопросам: сначала observable горячий (форма подчиняется), потом после switchMap
превращается в холодный observable, не так ли?
Я не думаю, что это обходной путь в этом случае. У вас есть компонент, и в этом компоненте вы хотите, чтобы доля был одним и тем же наблюдаемым между двумя подписками. Вы правы, вы не используете ПоведениеТема, мой плохой, извините. Хотя ситуация такая же.
Вы подписались на metrics$
два раза, вместо этого вы можете использовать синтаксис as
, как показано ниже
<div *ngIf = "metrics$ | async as metric; else loading">
<!-- Statements when metrics data found -->
</div>
<ng-template #loading>
<!-- Loading stuff... -->
<div class = "row" style = "margin: 1.54em;">
</ng-template>
Подробнее см. Обработка наблюдаемых с помощью NgIf и Async Pipe.
Где вы подписаны на
metrics$
?