Angular Перехватчик задержки HTTP-запроса не работает должным образом - PullRequest
0 голосов
/ 05 апреля 2020

Я хотел использовать перехватчик HTTP, чтобы каждый HTTP-запрос имел задержку в 500 мс между следующим. В настоящее время я делаю эти запросы от службы инъекций, которая зарегистрирована в app.module и добавлена ​​в мой компонент. В этом же модуле я зарегистрировал свой перехватчик.

// delay-interceptor.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
]

// manage-Houses.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();
            });
        });
    });
}

// manage-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-запрос, а в подписке я использую идентификатор нового дома для создания комнат. Для каждой комнаты я делаю POST-запрос с информацией о комнате и ID дома. Теперь это где проблема появляется. Между каждым домашним запросом задержка работает, но между всеми комнатами дома это не так, и я не могу понять, почему это происходит.

Я полагаю, это может быть как-то связано с вызовом одного и того же метод внутри каждого foreach, который, вероятно, будет повторно использовать одну и ту же наблюдаемую или что-то подобное, и, следовательно, не запускать перехватчик HTTP, но я не уверен. На перехватчике я попытался использовать таймер и задержку, но я получил одинаковый результат с обоими подходами.

Ответы [ 2 ]

1 голос
/ 05 апреля 2020

как вы думаете, что каждый запрос займет максимум 500 мс? это может занять больше времени, чем

Вы пытались использовать async/await?

вы можете использовать await для обработки этого асинхронного кода, также лучше избегать использования forEach в асинхронном коде, так как forEach не выполняет обещаний, так он и был разработан лучше использовать обычный for loop или ES6 for of loop

также нам нужно git избавиться от подписки и отписаться, как сейчас, используя async/await, нам нужно разобраться с promises вместо observables

для этого RxJS предоставляет оператор toPromise(), который преобразует Observable в promise, так что вы можете работать с методами HttpClient, используя вместо этого promises из Observables

toPromise() возвращает Promise, который разрешается с первым значением, выданным этим Observable (он внутренне вызывает 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()
        }
    }
}

надеюсь, что она работает так, как вам нужно

0 голосов
/ 07 апреля 2020

Не правильно изменять поведение перехватчика, потому что это повлияет на все запросы. Вы можете сделать это непосредственно из компонента или создать службу для этого прототипа.

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();
...