Реализовать перехватчик Angular для определения состояния сети - PullRequest
0 голосов
/ 20 июня 2020

У меня есть приложение angular, и я хочу, чтобы оно работало таким образом для каждого HTTP-запроса:

  1. Не отправлять запрос, если нет сети, и выдает ошибку
  2. Отменить запрос и выдать ошибку, если состояние сети было изменено на "офлайн"
  3. Отменить запрос и выдать ошибку, если нет ответа после X миллисекунд
  4. Вернуть ответ, если все прошло ОК

Прямо сейчас я создал эту службу, которая дает мне состояния сети:

export class ConnectionStateService {
  private connectionState = new Subject<ConnectionState>()
  private onlineObservable = fromEvent(window, 'online')
  private offlineObservable = fromEvent(window, 'offline')

  constructor() {
    this.onlineObservable.subscribe(event => this.connectionState.next(ConnectionState.ONLINE))
    this.offlineObservable.subscribe(event => this.connectionState.next(ConnectionState.OFFLINE))
  }

  getConnectionState() {
    return this.connectionState.asObservable()
  }

  getOfflineUpdates() {
    return this.offlineObservable
  }

  getCurrentConnectionState() {
    return navigator.onLine ? ConnectionState.ONLINE : ConnectionState.OFFLINE
  }
}

И реализовал этот Http Interceptor:

const MAX_REQUEST_TIME = 10000

intercept(req, next) {
    if (this.connectionStateService.getCurrentConnectionState() === ConnectionState.OFFLINE)
      return throwError(new HttpErrorResponse({error: 'Internet is required'}))

    return race(
      this.connectionStateService.getOfflineUpdates().pipe(mapTo(false)),
      timeout(MAX_REQUEST_TIME),
      next.handle(req)
    )
  }

Итак пока перехватчик обрабатывает случаи 1 и 4, но по какой-то причине timeout(MAX_REQUEST_TIME) не работает, а также this.connectionStateService.getOfflineUpdates().pipe(mapTo(false)) не выдает false, когда я отключаюсь от сети после отправки запроса. Что я здесь делаю не так?

1 Ответ

0 голосов
/ 25 июня 2020

Я думаю, проблема в том, что next.handle() всегда будет win , потому что при отправке запроса, помимо ответа / ошибки, этот наблюдаемый также испускает Sent событие :

// Fire the request, and notify the event stream that it was fired.
xhr.send(reqBody!);
observer.next({type: HttpEventType.Sent});

В этом случае вы могли бы использовать оператор filter:

race(
  this.connectionStateService.getOfflineUpdates().pipe(mapTo(false)),
  timeout(MAX_REQUEST_TIME),
  next.handle(req).pipe(filter(e => e.type !== HttpEventType.Sent))
)
...