如何在 Angular 8 中用相同的事件中断先前的发射

How to interrupt previous emits with the same event in Angular 8

我有一个应用程序,每当用户在 table 中选择一行时,它就会刷新数据网格 table。为了简单起见,我有一个示例代码:

子-component.ts

public jsonData = {...} //api request

this.rowSelectedEvent.subscribe(() => {
  this.refreshData(this.jsonData) 
})

function refreshData(jsonData){
  this.httpService.post(`${environment.BASE_URL}/api`, jsonData.payload).subscribe(
    result => {
      this.resultData = result.data
    }, 
    err => {
      console.error(err)
    }
  )
}

当用户点击 table 的一行时,rowSelectedEvent 在 HTML 中被触发。这将是一个例子:

app.component.html

<table>
  <row (click)="notifyRowSelected"></row>
</table>

app.component.ts

@Output() rowSelectedEvent: EventEmitter<string> = new EventEmitter();

[...]

function notifyRowSelected(){
  this.rowSelectedEvent.emit()
}

这段代码工作正常,收到带有新数据的 API 响应,服务器端进行计算和 returns 新值持续大约 4-5 秒。当用户重复或在少量时间内点击几行时出现问题,因为应用程序疯狂并多次刷新数据而不是一次(最后一次)。我尝试使用 unsubscribe() 但后来我无法再次订阅,因此功能丢失。我也试过 switchMap() 但由于某种原因,当我调试代码时它没有进入它。

想法是当用户单击新行时停止挂起的进程,让最后一次单击成为进行计算和接收响应的单击。有什么建议吗?

您可以使用 rxjs 的强大功能来处理这个问题

private makeCall(data) {
  return this.http.post(...);
}
this.rowSelectedEvent.pipe(
   map(() => this.jsonData),
   distinctUntilChanged(), // to skip the same events in a row
   switchMap((data) => this.makeCall(data)),
).subscribe((result) => this.resultData = result.data)

所有需要的力量都在 switchMap 运算符中。每当新事件到来时,它会取消先前的订阅(如果尚未完成,您将在网络选项卡中看到已取消的红色请求)并且订阅内的处理程序将仅接收最后一个事件