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".

2 ответа

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

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

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

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

Метод 2 - Observable Оберните вашу функцию API в наблюдаемый объект и прослушайте наблюдаемый объект, завершенный вonSave функция

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

onSave() {
 this.myApi.subscribe(() => {
  //Api is completed
 })
}

Вы можете привязаться к событию 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);
}
Другие вопросы по тегам