简体   繁体   English

Angular RxJS - 需要等到订阅以其他方法完成

[英]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.我有一个场景,当用户输入文本时,我必须点击 API 并保存输入的数据。 As it will be inefficient to hit API for every keystroke.因为每次击键都点击 API 是低效的。 so I have used 'fromEvent' RxJs operator to debounce for a second.所以我使用了 'fromEvent' RxJs 运算符来消抖一秒钟。

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.问题是我无法更新 HTML(因为我在这里简化了 HTML,但在我的项目中它是一个可折叠的面板,它会导致一些我不想要的 HTML 元素消失)因为我输入数据所以这就是原因我将响应存储在一个临时变量“recentResponse”中,并在单击“保存”按钮时更新 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).但这里的问题是,如果用户输入非常快并单击“保存”按钮,则订阅完成需要几秒钟的时间,直到那时 'recentResponse' 未定义,因此 'patientInformation' 永远不会得到更新(HTML 也是如此)。

How can I wait until Subscribe is finished inside onSave()?我怎样才能等到订阅在 onSave() 内完成? I need to wait until 'recentResponse' has some response.我需要等到 'recentResponse' 有一些回应。

You could bind to the keyup event, and use javascript timeout to defer the execution until the typing has stopped.您可以绑定到 keyup 事件,并使用 javascript timeout 推迟执行,直到输入停止。

html 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.我建议不要在keyupkeydownkeypress等事件上调用 API,它会在每次按键时击中服务器,而是添加blur事件。

To answer your question回答你的问题

Method 1 - Prevent button click Just disable button until API is completed.方法 1 - 防止按钮单击仅禁用按钮,直到 API 完成。

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方法 2 - Observable将 API 函数包装在 observable 中,并在onSave函数中监听 observable 完成

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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