Javascript 角度HTTP请求延迟侦听器未按预期工作

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

我想使用HTTP拦截器,这样每个HTTP请求在下一个请求之间都有500毫秒的延迟。我目前正在从一个在app.module上注册并注入到我的组件中的可注入服务发出这些请求。在同一个模块中,我注册了我的拦截器

//延迟截获器

@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
或ES6
for 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
的方法,以更被动的方式实现相同的结果