[英]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.