Как задержать определенные HTTP-запросы на HTTP-перехватчике в Angular - PullRequest
0 голосов
/ 08 июля 2019

У меня есть угловой код, и история такова.У меня 3 HTTP-вызова, и из одного вызова мне нужен специальный заголовок (X), который требуется для двух других HTTP-вызовов, и я не могу контролировать выполнение этих вызовов.Поэтому, когда HTTP-вызов, требующий заголовка X, идет перед HTTP-вызовом, который дает мне заголовок X, как я могу удержать вызов и позволить определенному HTTP-вызову пойти и получить заголовок X и продолжить остальные вызовы с помощьюЗаголовок X добавлен к остальным HTTP-вызовам?Может показаться, что я пытаюсь создать очередь HTTP-вызовов, пока не получу заголовок X и не продолжу остальные вызовы снова.Некоторая помощь будет оценена.Код выглядит следующим образом.

шаблон:

<button class="btn btn-primary" (click)="do()"> Do </button>

Файл App.ts

 export class AppComponent {
  constructor(private dataService: DataService) {}
  public do(): void {
    this.dataService.first().subscribe();
    this.dataService.second().subscribe((res) => {
      this.dataService.third().subscribe();
    });
  }
}

data-service.ts, который имеет 3 HTTP-вызова

const httpOptions1 = {
  headers: new HttpHeaders({ 'A': 'A' })
};

const httpOptions2 = {
  headers: new HttpHeaders({ 'X': 'X' })
};

const httpOptions3 = {
  headers: new HttpHeaders({ 'B': 'B' })
};

@Injectable()
export class DataService {

  private apiUrl = 'https://jsonplaceholder.typicode.com/posts';

  constructor(private http: HttpClient) {}

  public first(): Observable<any> {
    console.log('Call One')
    return this.http.get(`${this.apiUrl}`, httpOptions1);
  }

  public second(): Observable<any> {
    console.log('Call Two')
    return this.http.get(`${this.apiUrl}`, httpOptions2);
  }

  public third(): Observable<any> {
    console.log('Call Three')
    return this.http.get(`${this.apiUrl}`, httpOptions3);
  }
}

Это второй вызов с моим заголовком X, и от Interceptor я хочу сделать следующее: когда вызов first() сработает, я хочу удержать его, добавить и разрешить вызов second()и получите заголовок X, а затем повторно выполните вызов first() с уровня перехватчика.

Ниже приведен код перехватчика

private pocessed: boolean = false;
  private queue: any[] = [];

  constructor() {}

  public intercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<any> {
        /**
         * Filter a certain http call with a certain X http header where this call provides a new header
         * to be appended to all other http calls
         */
        if (req.headers.has('X')) {
            return delegate.handle(req).do((event) => {
                if (event.type === HttpEventType.Response) {
                    // new header data acquired; hence the boolean turned to true
                    this.pocessed = true;
                }
            });
        } else if (this.pocessed) {
            /**
             * if new header data acquired, append the new header to the rest of the calls
             */
            if (this.queue.length > 0) {
                // append header data to previous http calls
                this.queue.forEach(element => {
                    let request = new HttpRequest(element.req['method'], element.req['url'], element.req['body'], {
                        headers: element.req['headers'],
                        reportProgress: true,
                        params: element.req['params'],
                        responseType: element.req['responseType'],
                        withCredentials: element.req['withCredentials']
                    });

                    // this.fakeIntercept(request, element.next);
                });
            }
            // if new header data acquired, append the header to the rest of the calls
            req = req.clone({ setHeaders: { 'X': 'X' } });
            return delegate.handle(req).do((event) => console.log(event));
        } else {
            /**
             * these http calls need X header but the call to get the X header hasnt gone yet
             * therefor storing these calls in a queue to be used later when the header arrives
             */
            this.queue.push({req: req, next: delegate});
            return Observable.empty<any>();
        }
    }

    fakeIntercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<any> {
        req = req.clone({ setHeaders: { 'X': 'X' } });
        return delegate.handle(req);
    }

Если вам, ребята, нужны какие-либо разъяснения, пожалуйста, нажмитеменя в комментариях.Если вы видите что-то, что я сделал неправильно, пожалуйста, поделитесь со мной.Любые улучшения в коде приветствуются.

1 Ответ

0 голосов
/ 09 июля 2019

Я нашел решение, и оно довольно хорошо для меня.Я использую поток SUbject, чтобы имитировать поведение очереди и позволить запросам складываться, пока я не получу данные из http-вызова X-заголовка.Ниже приведен код.Надеюсь, это имеет смысл.Ура!

public intercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<any> {
        return Observable.create(observer => {
            if (req.headers.has('X') && this.headerAcquired == false) {
                this.headerAcquired = true;
                const subscription = delegate.handle(req).subscribe(event => {
                    if (event instanceof HttpResponse) {
                        this.pocessed = true;
                        this.requestSetter({key: this.pocessed});
                        this.removeRequest(req);
                        observer.next(event);
                    }
                },
                err => {
                    this.removeRequest(req);
                    observer.error(err);
                },
                () => {
                    this.removeRequest(req);
                    observer.complete();
                });
                // remove request from queue when cancelled
                return () => {
                    this.removeRequest(req);
                    subscription.unsubscribe();
                };
            } else {
                this.requests.push(req);

                this.requestGetter().subscribe(res => {
                    const i = this.requests.indexOf(req);
                    if (i >= 0) {
                        this.subjectInit = true;
                        this.requests.splice(i, 1);
                        req = req.clone({ setHeaders: { 'X': 'X' } });
                        const subscription = delegate.handle(req).subscribe(event => {
                            if (event instanceof HttpResponse) {
                                this.pocessed = true;
                                this.request.next(true);
                                this.removeRequest(req);
                                observer.next(event);
                            }
                        },
                        err => {
                            this.removeRequest(req);
                            observer.error(err);
                        },
                        () => {
                            this.subjectInit = false;
                            this.removeRequest(req);
                            observer.complete();
                        });
                        // remove request from queue when cancelled
                        return () => {
                            this.removeRequest(req);
                            subscription.unsubscribe();
                            this.request.unsubscribe();
                        };
                    }
                });
...