繁体   English   中英

Angular HTTP 请求延迟拦截器未按预期工作

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM