как подписаться в результате условной подписки
Я пытаюсь выполнить 3 асинхронных действия (наблюдаемые), одно внутри другого. 1. Первая наблюдаемая - это ответ модального диалогового окна eventEmiter - остальная часть потока зависит от его ответа (скажем, модальный логический эмиттер возврата относительно: "Вы хотите удалить элемент"). 2. Вторая наблюдаемая - это действие обновления (удаления) 3. Третья - получение новых данных после удаления.
Я использую rxjs- и пытаюсь понять, как это сделать без подписки в подписке. Смотрите мой код:
subscriptions : Subscription[] = [];
openDeleteDialog(data : any)
{
const modalRef : NgbModalRef = this.modalService.open(ConfirmationDialogComponent); //Modal dialoge reference
this.subscriptions.push(modalRef.componentInstance.passResult.subscribe(
(result =>//This is the response from the modal dialog
{
if (result)
{
let updateApi : UpdateApi = new UpdateApi(data);
this.srv.updateData(updateApi).pipe( //This is the update operation
tap(() =>
{
this.srv.getData(); //This is the fetch data operation
}
)
).subscribe();
}
}
)
));
}
3 ответа
Для этого вы можете использовать pipe, filter и switchMap:
subscriptions : Subscription[] = [];
openDeleteDialog(data : any)
{
const modalRef : NgbModalRef = this.modalService.open(ConfirmationDialogComponent); //Modal dialoge reference
this.subscriptions.push(
modalRef.componentInstance.passResult
.pipe(
filter((result) => !!result),
switchMap((result) => {
let updateApi : UpdateApi = new UpdateApi(data);
return this.srv.updateData(updateApi);
}),
switchMap((updateResult) => this.srv.getData())
).subscribe((getDataResult) => console.log(getDataResult))
);
}
Сначала вы используете фильтр, чтобы передавать данные только тогда, когда результат является чем-то, затем вы переключаетесь на новую наблюдаемую, наблюдаемую обновленную информацию, и в то же время вы передаете ее, чтобы переключиться на наблюдаемые данные получения. Таким образом, вы связываете наблюдаемые объекты, я предполагаю, что вам нужно дождаться результата обновления данных, чтобы снова получить данные.
РЕДАКТИРОВАТЬ: Дополнительная информация, вы использовали касание для вызова this.srv.getData()
, но если это возвращает наблюдаемое с HTTP-запросом, этот запрос никогда не будет вызван, так как вам нужно подписаться на него, чтобы запрос был выполнен. Как правило, я использую отводную трубу для побочных эффектов, которые будут нуждаться только в результате наблюдаемого, но не буду изменять ничего другого, связанного с наблюдаемым, если это имеет смысл.
Ты можешь использовать mergeMap
а также iif
оператор;
const subscription = modalRef.componentInstance.passResult
.pipe(mergeMap(result => iif(() => result, of(result))))
.pipe(mergeMap((result) => {
let updateApi : UpdateApi = new UpdateApi(data);
return this.srv.updateData(updateApi);
}))
.pipe(tap(() => this.srv.getData()))
.subscribe();
this.subscriptions.push(subscription);
Вместо массива подписок используйте тему с takeUntil
finalised = new Subject<void>();
а затем возьмитесь за последний оператор в наблюдаемой цепочке
modalRef.componentInstance.passResult.pipe(
filter(result => result)
switchMap(_ => this.srv.updateData(new UpdateApi(data)),
switchMap(_ => this.srv.getData()),
takeUntil(this.finialised)
).subscribe(updatedDataAfterDelete => {
// Do stuff with updated data
});
и в вашем ngOnDestroy
this.finialised.next();
this.finialised.complete();
Таким образом, вы можете заполнить все подписки одним субъектом, а не помещать их в массив подписок.