我有一个切换开关,可以在触发时发出 http PATCH 请求。您可以在下面看到它的样子:
模板:
<div id="toggle-status-btn-container">
<div class="slider" [ngClass]="{'to-right': !shopIsOpen}"></div>
<div class="label-container">
<label class="store-opened" (click)="updateShopSlotsStatus(true)" [ngClass]="{'toggled-opened-text': !shopIsOpen}">OPENED</label>
</div>
<div class="label-container">
<label class="store-closed" (click)="updateShopSlotsStatus(false)" [ngClass]="{'toggled-closed-text': !shopIsOpen}">CLOSED</label>
</div>
</div>
效果很好,但现在用户可以通过这个切换开关发送垃圾邮件,连续触发多个 http 请求。
我能做些什么来防止这种行为?如果用户向这个切换开关发送垃圾邮件,我不想触发 http 请求。也许有办法只触发最后一个?由于我对 RxJs 很陌生,我真的不知道如何解决这个问题。
这里是点击事件调用的方法,在组件.ts中:
updateShopSlotsStatus(isOpen: boolean){
this.shopIsOpen = isOpen;
this.apiService.updateShopSlotsStatus(isOpen, this.weekDay).subscribe();
}
还有 http 请求,在一个服务文件中:
updateShopSlotsStatus(isOpen: boolean, weekDay: string){
const endpoint = this.url + "shipping/" + this.webzineId + "/delivery_slots" + "/";
return this.http.patch(endpoint, {"slots": { [weekDay] : { "enabled": isOpen }}});
}
提前致谢。
答案 0 :(得分:2)
您可能希望像在 this StackBlitz 中一样使用 BehaviorSubject
和 switchMap
的组合。
在这里,我将打开和关闭按钮绑定到一个更改 BehaviorSubject
值的函数,如下所示:
模板:
<button
(click)="updateShopSlotsStatus(true)"
[ngClass]="{'selected': shopSlotStatus$ | async}"
>
OPEN
</button>
<button
(click)="updateShopSlotsStatus(false)"
[ngClass]="{'selected': !(shopSlotStatus$ | async)}"
>
CLOSED
</button>
ts:
updateShopSlotsStatus(isOpen: boolean) {
this.shopSlotStatusSubject$.next(isOpen);
}
然后您可以像这样观察 BehaviorSubject
上的变化:
private shopSlotStatusSubject$: BehaviorSubject<
boolean
> = new BehaviorSubject(false);
// shared so only one subscription is maintained
private readonly shopSlotStatus$ = this.shopSlotStatusSubject$
.asObservable()
.pipe(share());
readonly changeSlotStatus$ = this.shopSlotStatus$.pipe(
// you could introduce a debounceTime here if you wanted
// debounceTime(500),
tap(() => (this.changingStatus = true)),
// faked API call here
switchMap(status => this.appService.updateShopSlotsStatus(status)),
tap(() => (this.changingStatus = false))
);
如果源(在本例中为 switchMap
observable)发出,changeSlotStatus$
运算符将取消任何飞行中的 observable。
我在 Stackblitz 中包含了 exhaustMap
和 mergeMap
的导入。将 switchMap
更改为这两个运算符以查看它们的工作方式有何不同。 exhaustMap
将忽略所有后续发射,直到正在进行的发射完成,而 mergeMap
将触发与按下按钮一样多的请求。我会让你来决定哪种方法最好!您可以在 learn rxjs. 了解更多信息。我建议您阅读 RxJS 和不同的运算符以及如何使用 pipe
组合它们。 RxJS 是个好东西。
如果您想在请求正在进行时禁用按下的按钮,您也可以绑定到 changingStatus
布尔值。