Angular HttpInterceptor не срабатывает на вложенных Observables

У меня есть HttpInterceptor, чтобы добавить мой токен Bearer ко всем вызовам моего WebApi. Этот перехватчик отлично работает на всех моих простых сервисных вызовах.

Но у меня есть одно место, где мне нужно вызвать 2 метода и использовать оба результата для построения комбинированной модели. Я уже использовал MergeMap, ForkJoin и FlatMap для вложения наблюдаемых, но ни один из них, похоже, не запускает мой HttpInterceptor ...

Это перехватчик

export class JwtInterceptor implements HttpInterceptor {

    constructor(private userService: UserService) { }

    public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // add authorization header with jwt token if available
        let currentUser = this.userService.getCurrentUser();
        if (currentUser && currentUser.token) {
            request = request.clone({
                setHeaders: {
                    Authorization: `Bearer ${currentUser.token}`
                }
            });
        }

        return next.handle(request);
    }
}

Служба звонков

public getPriceList(): Observable<CuttingGapPartPrice[]> {
    const list = sessionStorage.getItem(this.listSessionKey);
    if (list) {
        return of(JSON.parse(list) as CuttingGapPartPrice[]);
    }

    return super.getClient()
        .get(`/api/cutting-gap-part-prices`, { headers: super.getHeaders() })
        .pipe(map(response => {
            sessionStorage.setItem(this.listSessionKey, JSON.stringify(response));
            return response ? response as CuttingGapPartPrice[] : new Array<CuttingGapPartPrice>();
        }));
}

public getPowerList(): Observable<MotorPower[]> {
    const list = sessionStorage.getItem(this.listSessionKey);
    if (list) {
        return of(JSON.parse(list) as MotorPower[]);
    }

    return super.getClient()
        .get(`/api/motor-power`, { headers: super.getHeaders() })
        .pipe(map(response => {
            sessionStorage.setItem(this.listSessionKey, JSON.stringify(response));
            return response ? response as MotorPower[] : new Array<MotorPower>();
        }));
}

По отдельности они работают идеально. Но комбинированных / вложенных их нет.

Вложенный вызов с использованием MergeMap

public getQuotationPrices(quotation: Quotation): Observable<QuotationPrices> {
    return this.cuttingGapPartPriceService.getPriceList().pipe(mergeMap(prices => {
        return this.motorPowerService.getPowerList().pipe(map(powers => {
            var result = new QuotationPrices();
            //Some custom logic

            return result;
        }));
    }));
}

Я знаю, что моя проблема сравнима с тем, что описано в этом сообщении, но Я просто не понимаю, как это исправить.

Изменить - вложенный вызов с использованием ForkJoin

public getQuotationPrices(quotation: Quotation): Observable<QuotationPrices> {
    return forkJoin([this.cuttingGapPartPriceService.getPriceList(), this.motorPowerService.getPowerList()]).pipe(map(data => {
        const prices = data[0];
        const powers = data[1];
        var result = new QuotationPrices();


        return result;
    }));
}

Результаты на вкладке сети Chrome  Результаты на вкладке сети Chrome


person Beejee    schedule 24.03.2019    source источник
comment
Я действительно не понимаю, как второй фрагмент связан с третьим. Я предполагаю, что вы никогда не подписываетесь на возвращаемый наблюдаемый объект. Или что все ваши данные уже находятся в хранилище сеанса, и поэтому ни один запрос не отправляется. Если да, то опубликуйте полный минимальный пример, воспроизводящий проблему, в виде stackblitz.   -  person JB Nizet    schedule 24.03.2019
comment
@JBNizet Я переименовал методы getList, чтобы вам было понятнее, ребята, но я забыл переименовать их во вложенном вызове (теперь исправлено). На getQuotationPrices подписывается, и в хранилище сеанса нет данных. Я вижу, что вызов выполняется на вкладке сети в инструментах разработчика Chrome. Вызов возвращает 401, потому что в заголовках отсутствует токен-носитель.   -  person Beejee    schedule 24.03.2019


Ответы (2)


Попробуйте сгладить вложенные наблюдаемые объекты. Возможно, ваши внутренние наблюдаемые объекты не подписываются (Observables не запускается, если они не подписаны). Вы можете проверить этот пример stackblitz, чтобы увидеть, как вложенные наблюдаемые объекты не выполняются, если вы не подписаны на innerObservables или сгладить их. Также, как предлагает @JB Nizet, было бы здорово, если бы вы могли создать репо на stackblitz

person Shadab Faiz    schedule 24.03.2019
comment
Я уже использовал flatMap, и это ничего не решило. Я подписываюсь на наблюдаемое, возвращаемое getQuotationPrices. Я вижу, что выполняется вызов первого наблюдаемого (getPriceList) на вкладке сети инструментов разработчика Chrome. Вызов возвращает 401, потому что в заголовках отсутствует токен-носитель. - person Beejee; 24.03.2019

Наконец выяснил, в чем проблема. Это не имело ничего общего с наблюдаемыми. Я предоставил перехватчики в AppModule, но они были снова переопределены моим SharedModule, потому что я снова импортировал HTTPClientModule angular. Проблема была устранена после удаления дублирующего импорта.

person Beejee    schedule 24.03.2019
comment
Хм, в этом не должно быть необходимости. Я предполагаю, что вы импортировали HttpClientModule в свой ленивый модуль. - person JB Nizet; 24.03.2019
comment
Я добавил эту часть провайдера в свой AppModule. {предоставить: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true}, - person Beejee; 24.03.2019
comment
нашел настоящую причину (изменил свой ответ) - person Beejee; 24.03.2019
comment
Рад слышать. Это именно то, что я вам тогда сказал :-) - person JB Nizet; 25.03.2019