Javascript 角度HTTP请求延迟侦听器未按预期工作
我想使用HTTP拦截器,这样每个HTTP请求在下一个请求之间都有500毫秒的延迟。我目前正在从一个在app.module上注册并注入到我的组件中的可注入服务发出这些请求。在同一个模块中,我注册了我的拦截器 //延迟截获器Javascript 角度HTTP请求延迟侦听器未按预期工作,javascript,angular,http,rxjs,delay,Javascript,Angular,Http,Rxjs,Delay,我想使用HTTP拦截器,这样每个HTTP请求在下一个请求之间都有500毫秒的延迟。我目前正在从一个在app.module上注册并注入到我的组件中的可注入服务发出这些请求。在同一个模块中,我注册了我的拦截器 //延迟截获器 @Injectable() 导出类DelayInterceptor实现HttpInterceptor{ 拦截(请求:HttpRequest,下一步:HttpHandler):可观察{ 返回计时器(500)。管道( 延迟(500), switchMap(()=>next.hand
@Injectable()
导出类DelayInterceptor实现HttpInterceptor{
拦截(请求:HttpRequest,下一步:HttpHandler):可观察{
返回计时器(500)。管道(
延迟(500),
switchMap(()=>next.handle(请求))
)
}
}
//app.module.ts
提供者:[
{
提供:HTTP_拦截器,
useClass:DelayInterceptor,
多:真的
},
经理室服务
]
//管理-house.component.ts
createHouses(){
this.houses.foreach((house:house)=>{
this.createHouseService.createHouse(house.name).subscribe(createdHouse=>{
house.rooms.foreach((房间:房间)=>{
this.createHouseService.createRoom(house.id,room.name).subscribe();
});
});
});
}
//管理-house.service.ts
createHouse(houseName:string):可观察{
返回this.httpClient.post(`this.apirl}/houses`,{houseName:houseName});
}
createRoom(houseId:string,roomName:string):可观察{
返回this.httpClient.post(`this.apirl}/houses/${houseId}/rooms`,{roomName:roomName});
}
在我的组件中,我必须以嵌套的方式发出请求。我有一个房屋列表,我想为每个房屋创建一个房间列表。因此,对于每栋房子,我都会发出一个POST请求,在订阅时,我会使用新创建的房子的ID来创建房间。对于每个房间,我都会发出一个带有房间信息和房屋ID的POST请求。现在问题就出现在这里。在每一个房间的请求之间,延迟是有效的,但是在一个房间的所有房间之间,延迟不是有效的,我不明白为什么会发生这种情况
我想这可能与在每个foreach中调用相同的方法有关,该方法可能会重用相同的可观察对象或类似的对象,因此不会触发HTTP侦听器,但我不确定。在拦截器上,我尝试使用计时器和延迟方法,但两种方法的结果都是一样的。你怎么认为每个请求最长需要500毫秒? 可能需要更长的时间 您是否尝试使用
async/await
您可以使用wait
来处理此异步代码,而且最好避免在异步代码中使用forEach
,因为forEach
不是承诺感知的,这就是它的设计方式
因此,最好使用普通for loop
或ES6for of loop
此外,我们需要使用async/await
取消订阅和取消订阅,我们需要处理承诺
而不是可观察的
为此,RxJS
提供了toPromise()
操作符,该操作符将可观察的
转换为承诺
,因此您可以使用HttpClient
方法,而不是可观察的
toPromise()
返回一个Promise
,该值由该observeable
发出的第一个值解析(它在内部为您调用subscribe
,并用Promise
对象包装)
然后可以将createHouses
函数更新为类似的函数
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();
这个拦截器不会将你的请求间隔500毫秒,而是将它延迟500毫秒,这是不同的行为。啊,我明白了,我想这是有道理的。是否可以使用拦截器按给定的时间量分隔请求?是的,这是可能的,您需要使用拦截器创建一个队列,并每隔500毫秒触发一个队列请求。我现在在手机上,但我会尽快写一个详细阐述这个想法的答案。我认为您应该尝试另一种解决方案,以解决这些嵌套的请求方式,尝试使用类似于
forkjoin
或zip
的方法,以更被动的方式实现相同的结果