Angular RxJS - нужно дождаться завершения подписки другим методом

@Component({
  selector: 'note-consultant',
  template: '<div>
    <div>{{patientInformation}}</div>
    <textarea #textElemRef></textarea>
    <button (click)="onSave()">Done</button>
    </div>'
})
export class NoteConsultantComponent implements OnInit, AfterViewInit { 
    recentResponse:any;
    patientInformation:any;
    @ViewChild('textElemRef') textElemRef: ElementRef;

    ngAfterViewInit(): void {
    fromEvent(this.textElemRef.nativeElement, 'keyup').pipe(
      map((event: any) => {
        return event.target.value;
      })
      ,debounceTime(1000)
    ).subscribe((text: string) => {

      let request = this.buildRequestItem(text);
        this.patientService.saveProblemNotes(request).subscribe((resp: any) => {
            if (resp.error) {
              console.log(resp.error);
              return;
            }

            //update response in temp variable...
            this.recentResponse = resp.problemText;
            }
        });
    }
    onSave() {
       if (this.recentResponse != null) {    
       //when clicking save button update DOM
       this.patientInformation = this.recentResponse;
     }

      //Reset temp variable
      this.recentResponse = null;
    }
}

У меня есть сценарий, когда пользователь вводит текст, который мне нужно нажать на API и сохранить введенные данные. Так как будет неэффективно нажимать на API для каждого нажатия клавиши. поэтому я использовал оператор RxJs fromEvent для устранения дребезга на секунду.

Дело в том, что я не могу обновлять HTML (потому что я упростил HTML здесь, но в моем проекте это сворачиваемая панель, это приведет к исчезновению нескольких элементов HTML, чего я не хочу) при вводе данных. Вот причина Я сохраняю ответ во временной переменной «recentResponse» и после нажатия кнопки «Сохранить» обновляю HTML.

Но проблема здесь в том, что если пользователь печатает очень быстро и нажимает кнопку «Сохранить», это занимает несколько секунд, пока подписка не будет завершена, до тех пор, пока «recentResponse» не будет определен, поэтому «patientInformation» никогда не будет обновляться (так же, как и HTML).

Как я могу дождаться завершения подписки внутри onSave()? Мне нужно подождать, пока 'recentResponse' не ответит.


person Mudassir Hussain    schedule 07.02.2020    source источник
comment
вы можете использовать оператор задержки RxJs Delay, который часто используется случаи для этого оператора, и пример для чего-то подобного   -  person rmjoia    schedule 07.02.2020
comment
Ознакомьтесь с оператором SwithMap.   -  person rmjoia    schedule 07.02.2020


Ответы (2)


Вы можете привязаться к событию keyup и использовать тайм-аут javascript, чтобы отложить выполнение до тех пор, пока набор текста не прекратится.

html

<input type="text" (keyup)="onKeyUp($event)" />

машинопись

timeout: number;

onKeyUp(event): void {
  if (this.timeout) {
    window.clearTimeout(this.timeout);
  }

  this.timeout = window.setTimeout(() => {
    // TODO: process key up here
  }, 500);
}
person Kurt Hamilton    schedule 07.02.2020
comment
ОП спрашивает о том, как использовать RxJ и как ждать, используя его ... ваш ответ использует RxJ? - person rmjoia; 07.02.2020
comment
Последние 2 абзаца ОП описывают проблему в более общем виде. Методы rxjs — один из способов решения проблемы. setTimeout — еще один способ решения проблемы. Просто потому, что в какой-то момент будет использоваться rxjs, это не делает его проблемой именно rxjs. - person Kurt Hamilton; 07.02.2020

Я бы посоветовал не вызывать API для таких событий, как keyup, keydown, keypress и т. д., он будет поражать сервер при каждом нажатии клавиши. Вместо этого добавьте событие blur.

Чтобы ответить на ваш вопрос

Способ 1 – Предотвратить нажатие кнопки Просто отключите кнопку, пока API не будет завершен.

fromEvent().subscribe(() => {
 disableBtn = true;
 this.patientService.saveProblemNotes(request).subscribe(() => {
  disableBtn = false; 
 })
})

Метод 2 – наблюдаемый. Заключите функцию API в наблюдаемый объект и прослушайте его завершение в функции onSave.

myApi() {
 new Observable(observer => {
  this.patientService.saveProblemNotes(request).subscribe(() => {
   observer.next();
  });
 });
}

onSave() {
 this.myApi.subscribe(() => {
  //Api is completed
 })
}
person Sameer    schedule 07.02.2020