简体   繁体   中英

Angular RxJS - Need to Wait until Subscribe has finished in other method

@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;
    }
}

I have a scenario when the user types text I have to hit API and save the typed data. As it will be inefficient to hit API for every keystroke. so I have used 'fromEvent' RxJs operator to debounce for a second.

The thing is that I can't update HTML(because I have simplified the HTML here but in my project its a collapsible panel, it will cause few HTML elements to disappear which I don't want) as I type data So that's the reason I store the response in a temporary variable 'recentResponse' and upon clicking Save button I update HTML.

But the problem here is if user types very fast and clicks Save button, it takes few seconds until Subscribe is finished, until then 'recentResponse' is undefined thus 'patientInformation' never gets updates(so does HTML).

How can I wait until Subscribe is finished inside onSave()? I need to wait until 'recentResponse' has some response.

You could bind to the keyup event, and use javascript timeout to defer the execution until the typing has stopped.

html

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

typescript

timeout: number;

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

  this.timeout = window.setTimeout(() => {
    // TODO: process key up here
  }, 500);
}

I would suggest not to call API on events like keyup , keydown , keypress etc., It will hit the server on every key press, Instead add blur event.

To answer your question

Method 1 - Prevent button click Just disable button until API is completed.

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

Method 2 - Observable Wrap you API function in observable and listen for observable complete in onSave function

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM