Rxjs-带按钮的表,在按下最后一个按钮之后等待一段时间,然后再请求

时间:2019-06-07 13:02:20

标签: angular rxjs rxjs6

我希望您能将某些想法用于删除通知之类的事情。

基本上,我的用户有一个通知列表,可以将其标记为已读。
现在,我的后端非常呆滞(我无法控制它)。
现在,当用户单击通知的按钮:

  1. 向后端发出请求以标记通知,然后在后端响应后,使用另一个请求刷新数据;
  2. 该条目已在应用内存中修改,视图已修改
  3. 1。中的刷新数据返回,视图被修改

这会转变为类似的东西(使用Angular的HttpClient):

markAsRead(id: string): void {
  this.http.post(url, body, options)
  .subscribe(() => this.reloadNotifications());

  this.markAsReadInternal(id);
}

麻烦来了:当我的用户决定执行单个操作时,一切都很好。但是,当用户决定阅读许多通知时,可以在刷新数据时多次更改视图。

我可以看到一种预防问题的方法,但这意味着

  1. 单击按钮;
  2. 将ID存储在数组中
  3. 等待X毫秒以再次单击;
  4. 如果点击返回到 2。,否则
  5. 发送带有ID数组的请求并刷新数据

有什么帮助将其转换为rxjs代码吗?

奖励点:无论如何,我的数据每5秒刷新一次...

2 个答案:

答案 0 :(得分:1)

按钮点击调用函数:

Release

将存储按钮单击为主题/可观察的

<button (click)="buttonClicked()"></button>

为每次点击赋予新值:

private buttonClick$: Subject<any> = new Subject();

限制获取按钮的点击次数:

buttonClicked() {
  this.buttonClick$.next();
  // this.buttonClick$.emit(); // One of these is deprecated, can't remember which
}

然后您可以执行以下操作:

getButtonClicks() {
  return this.buttonClick$.pipe(
    throttleTime(5000)
  )
}

要通过点击来观察,您也可以使用它代替主题: https://www.learnrxjs.io/operators/creation/fromevent.html

编辑:

因此,您希望在节流之间保存点击。 您可以这样做:

getButtonClicks().subscribe(() => {
  // Do something with throttled button clicks
});

然后您仍然调用您的BE API:

getButtonClicks() {
  return this.buttonClick$.pipe(
    buffer(this.buttonClick$.pipe(
      debounceTime(5000)
    ))
  )
}

答案 1 :(得分:0)

最好使用bufferdebounceTime,然后再使用throttleTime

throttleTimedebounceTime

throttleTime首先发出(我想这不是您想要的),然后等待N ms。

https://rxjs-dev.firebaseapp.com/api/operators/buffer-buffer

debounceTime在上一个事件之后等待N毫秒,如果没有其他事件发出则发出。

https://rxjs-dev.firebaseapp.com/api/operators/debounceTime-debounceTime

buffer(observable)表示collect items until parameter observable emits,而debounceTime(N)表示N ms after last emit

您可以将其理解为“'收集项目直到'(buffer)'最后一次点击后1000毫秒'(debounceTime)”。

这是工作模拟。

// Mock notification button click event
const click$ = Rx.fromEvent(document.getElementById('notification'), 'click');

// Mock http request
function markAsRead(...ids: string[]) {
  return Rx.timer(Math.random() * 2000)
    .pipe(
      RxOp.mapTo('marked!'),
    );
}

click$
  .pipe(
    RxOp.mapTo((Math.random() * 1000).toFixed()), // Mock ID, random
    RxOp.bufferWhen(() => click$.pipe(RxOp.debounceTime(1000))), // your 'certain time'
    RxOp.switchMap(ids => markAsRead(...ids)), // call http request
  )
  .subscribe(value => log(value));

https://stackblitz.com/edit/kuroneko0441-rxjs-test-1ynvps?file=index.ts&devtoolsheight=50