我想問一下最佳實踐是什么或者如何使用exhaust Matp來防止多次提交?例如,當用戶向 SAVE 按鈕發送垃圾郵件時?例如基于下面的示例代碼,我們如何處理它一次只提交 1 個,即使是用戶垃圾郵件或單擊保存按鈕一百次。謝謝。
#html代碼
<ng-template #editButtons>
<div class="flex" *ngIf="isEditing">
<app-page-section-cards-btn
[btnData]="pageSectionsOptions.btnData.cancel"
(btnClickEvent)="cancelEdit()"></app-page-section-cards-btn>
<app-page-section-cards-btn
[btnData]="pageSectionsOptions.btnData.save"
(btnClickEvent)="saveDeal()">
</app-page-section-cards-btn>
</div>
</ng-template>
#ts 代碼
saveDeal(){
this.isLoading = true;
if(!this.isExistingDeal){
const dealTypeValues = {
"id": 0,
"name": this.dealPLSFormFields.dealName,
"summary": this.dealPLSFormFields.summary,
"mlasId": this.dealPLSFormFields.partner,
"startDate": "estimatedOtherRevenue":this.dealPLSFormFields.estimatedOtherRevenue,
"descriptionOfOtherRevenue":this.dealPLSFormFields.descriptionOfOtherRevenue,
"totalMonthlyRentAndFees":this.dealPLSFormFields.totalMonthlyRentAndFees,
"buildOutCostReimbursement":this.dealPLSFormFields.buildOutCostReimbursement,
"dealId": 0,
"startDateString": AppUtils.convertDateStringToYYYYMMDD(this.dealPLSFormFields.startDate),
"endDateString": AppUtils.convertDateStringToYYYYMMDD(this.dealPLSFormFields.endDate),
}
const payload = {
"id": 0,
"name": this.dealPLSFormFields.dealName,
"dealType": "Partner Location Submission",
"annualRentProposed": null,
"annualRentCurrent": null,
"firmTermRemaining": null,
"firmTermAdded": null,
"maxAvailableTerm": null,
"status": null,
"capitalContribution": null,
"parentCloneId": null,
"accountId": this.currentAccount.accountId,
"transactionId": this.transactionData.id,
"dealTypeValues": JSON.stringify(dealTypeValues)
}
this._dealService.createDeal(payload)
.pipe(debounceTime(500))
.subscribe(
res=>{
this.isLoading = false;
this._notificationService.showSuccess('Deal was successfully created.');
if(res.isSuccess){
this.refreshDealDetailsPage(res.data);
}
},
err=>{
console.log('Error creating deal')
}
)
}else{
const dealTypeValues = {
"id": this.dealData.dealTypeValues.id,
"name": this.dealPLSFormFields.dealName,
"summary": this.dealPLSFormFields.summary,
"mlasId": this.dealPLSFormFields.partner,
"startDate": AppUtils.convertDateStringToYYYYMMDD(this.dealPLSFormFields.startDate),
"endDate": AppUtils.convertDateStringToYYYYMMDD(this.dealPLSFormFields.endDate),
"securityMonitoringMonthly": this.dealPLSFormFields.securityMonitoringMonthly,
"rent": this.dealPLSFormFields.rent,
"cam": this.dealPLSFormFields.cam,
"supportServicesFee": this.dealPLSFormFields.supportServicesFee,
"estimatedOtherRevenue":this.dealPLSFormFields.estimatedOtherRevenue,
"descriptionOfOtherRevenue":this.dealPLSFormFields.descriptionOfOtherRevenue,
"totalMonthlyRentAndFees":this.dealPLSFormFields.totalMonthlyRentAndFees,
"buildOutCostReimbursement":this.dealPLSFormFields.buildOutCostReimbursement,
"dealId": this.dealData.dealTypeValues.dealId,
"startDateString": AppUtils.convertDateStringToYYYYMMDD(this.dealPLSFormFields.startDate),
"endDateString": AppUtils.convertDateStringToYYYYMMDD(this.dealPLSFormFields.endDate),
}
const payload = {
"id": this.dealData.id,
"name": this.dealPLSFormFields.dealName,
"dealType": "Partner Location Submission",
"annualRentProposed": null,
"annualRentCurrent": null,
"firmTermRemaining": null,
"firmTermAdded": null,
"maxAvailableTerm": null,
"status": this.dealData.status,
"capitalContribution": null,
"parentCloneId": null,
"accountId": this.currentAccount.accountId,
"transactionId": this.transactionData.id,
"dealTypeValues": JSON.stringify(dealTypeValues)
}
this._dealService.updateDeal(payload)
.pipe(debounceTime(500))
.subscribe(
res=>{
if(res.isSuccess){
this.isLoading = false;
this.refreshDealDetailsPage(res.data);
}
},
err=>{
this.isLoading = false;
console.log('Error updating deal')
}
)
}
}
}
uj5u.com熱心網友回復:
有兩種方法可以解決這個問題:
一種是使用RxJS操作debounceTime。此運算子每 X 毫秒僅允許 1 個請求通過將被訂閱呼叫的可觀察管道。因此,即使用戶發送垃圾郵件,每 X 時間也只會發送一個垃圾郵件。這在所有型別的請求中都很有用,而不僅僅是保存。
在您的情況下,假設 500 毫秒:
import { debounceTime } from 'rxjs/operators'; ... this._dealService.createDeal(payload) .pipe(debounceTime(500)) .subscribe( ...
編輯:Yuriy 建議的exhaustMap解決方案可以是一個更好的替代方案,因為如果請求慢于 500 毫秒,那么我們可以允許使用此解決方案進行雙重提交
解決此問題的另一種方法是在第一次單擊按鈕時禁用該按鈕,直到我們從后端獲得回應(成功或錯誤):
import { tap } from 'rxjs/operators'; ... this._dealService.createDeal(payload) .pipe( tap(() => this.saving = true), finalize(() => this.saving = false), ).subscribe( ...然后您可以在
app-page-section-cards-btn組件中添加禁用的邏輯<app-page-section-cards-btn [disabled]="saving" [btnData]="pageSectionsOptions.btnData.save" (btnClickEvent)="saveDeal()">
兩者的組合可能非常健壯,但如果您的應用程式周圍都有這種行為,則可以在您的所有組件中添加大量樣板代碼。然后建議可以debounceTime在 1) 部分的全域攔截器中執行邏輯。
uj5u.com熱心網友回復:
有兩種方法可以防止多次提交。
- 創建變數/主題以保存請求掛起/加載的資訊并禁用按鈕
- 創建登錄事件的主題。
this.loginSubject$.pipe( exhaustMap((loginData) => this.authService.login(loginData)) );
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/320954.html
標籤:javascript 有角的 打字稿
