簡體   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