[英]Angular HTTP request delay interceptor not working as expected
我想使用 HTTP 攔截器,以便每個 HTTP 請求在下一個請求之間有 500 毫秒的延遲。 我目前正在從在 app.module 上注冊並注入到我的組件中的可注入服務發出這些請求。 在同一個模塊中,我注冊了我的攔截器。
// 延遲攔截器.ts
@Injectable()
export class DelayInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return timer(500).pipe(
delay(500),
switchMap(() => next.handle(request))
)
}
}
// app.module.ts
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: DelayInterceptor,
multi: true
},
ManageHousesService
]
// 管理房屋.component.ts
createHouses() {
this.houses.foreach((house: House) => {
this.createHousesService.createHouse(house.name).subscribe(createdHouse => {
house.rooms.foreach((room: Room) => {
this.createHousesService.createRoom(house.id, room.name).subscribe();
});
});
});
}
// 管理-houses.service.ts
createHouse(houseName: string): Observable<House> {
return this.httpClient.post(`${this.apiUrl}/houses`, { houseName: houseName });
}
createRoom(houseId: string, roomName: string): Observable<Room> {
return this.httpClient.post(`${this.apiUrl}/houses/${houseId}/rooms`, { roomName: roomName });
}
在我的組件中,我必須以嵌套方式發出請求。 我有一個房屋清單,我想為每個房屋創建一個房間清單。 因此,對於每個房子,我都會發出一個 POST 請求,並在訂閱時使用新創建的房子的 ID 來創建房間。 對於每個房間,我都會使用房間信息和房屋 ID 發出 POST 請求。 現在這就是問題出現的地方。 在每個房屋請求之間,延遲都在起作用,但在房屋的所有房間之間卻沒有,我無法弄清楚為什么會這樣。
我想這可能與在每個 foreach 中調用相同的方法有關,這可能會重用相同的 observable 或類似的東西,因此不會觸發 HTTP 攔截器,但我不確定。 在攔截器上,我嘗試同時使用計時器和延遲方法,但兩種方法都得到了相同的結果。
您如何認為每個請求最多需要 500 毫秒? 可能需要更長的時間
您是否嘗試使用async/await
?
你可以使用await
來處理這個異步代碼,也最好避免在異步代碼中使用forEach
,因為forEach
不是promise-aware,這就是它的設計方式,所以最好使用普通for loop
或 ES6 for of loop
我們還需要 git 像現在一樣使用async/await
擺脫訂閱和取消訂閱,我們需要處理promises
而不是observables
為此, RxJS
提供了toPromise()
運算符,它將Observable
轉換為promise
,因此您可以使用promises
而不是Observables
來使用HttpClient
方法
toPromise()
返回一個Promise
,它使用該Observable
發出的第一個值解析(它在內部為您調用subscribe
並用Promise
對象包裝它)。
然后,您可以將createHouses
function 更新為類似
async createHouses() {
for (const house of this.houses) {
// wait for the house to be added to db
await this.createHousesService.createHouse(house.name).toPromise();
// then loop over the rooms
for (const room of house.rooms) {
// wait for the room to be added to the db
await this.createHousesService.createRoom(house.id, room.name).toPromise()
}
}
}
希望它能按你的需要工作
改變攔截器的行為是不正確的,因為它會影響所有的請求。 您可以直接從組件中執行此操作,或為此原型創建服務。
concat(
...this.houses.map((house: House) =>
this.createHousesService.createHouse(house.name).pipe(
delay(500),
concatMap((createdHouse) =>
concat(
...house.rooms.map((room: Room) =>
this.createHousesService
.createRoom(house.id, room.name)
.pipe(delay(500))
)
)
)
)
)
).subscribe();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.