как подписаться в результате условной подписки

Я пытаюсь выполнить 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();

Таким образом, вы можете заполнить все подписки одним субъектом, а не помещать их в массив подписок.

Другие вопросы по тегам