Используйте обещание в Угловом HttpClient Interceptor

Могу ли я использовать обещание в HttpInterceptor? Например:

export class AuthInterceptor implements HttpInterceptor{
this.someService.someFunction()
    .then((data)=>{
       //do something with data and then
       return next.handle(req);
    });
}

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

Мой перехватчик:

@Injectable()
export class AuthInterceptor implements HttpInterceptor{

    constructor(private authService: AuthService){}

    intercept(req: HttpRequest<any>, next: HttpHandler) : Observable<HttpEvent<any>>{
        console.log('Intercepted!');
        // return next.handle(req);
        this.authService.getToken()
            .then((token)=>{
                console.log(token);
                const reqClone = req.clone({
                    headers: req.headers
                            .set('Authorization', 'Bearer ' + token)
                            .append('Content-Type', 'application/json')
                });
                console.log(reqClone);
                return next.handle(reqClone);
            })
            .catch((err)=>{
                console.log('error in interceptor' + err);
                return null;
            });
    }
}

Запрос:

this.http.post(this.baseURL + 'hero', data)
                    .subscribe(
                            (res: any) => {
                                console.log('Saved Successfully.');
                                console.log(res);
                            },
                            (err: any) => {
                                console.log('Save Error.' + err);
                            }
                        );

Проблемы, с которыми я сталкиваюсь:

→ Я получаю эту ошибку до того, как обещание будет разрешено.

You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

Обещание восстанавливается, и я получаю свой токен, но после ошибки.

Ответы

Ответ 1

ОБНОВЛЕНИЕ: использование [email protected]

import { from, Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

    constructor(private authService: AuthService){}

    intercept(request: HttpRequest<any>, next: HttpHandler) : Observable<HttpEvent<any>>{
        return from(this.authService.getToken())
              .pipe(
                switchMap(token => {
                   const headers = request.headers
                            .set('Authorization', 'Bearer ' + token)
                            .append('Content-Type', application/json');
                   const requestClone = request.clone({
                     headers 
                    });
                  return next.handle(requestClone);
                })
               );
    }
}

ОРИГИНАЛЬНЫЙ ОТВЕТ

Да, вы могли бы внедрить требуемый сервис в метод конструктора перехватчика, а при реализации intercept получить значение, создать новый обновленный http-запрос и обработать его.

Я не очень хорош с обещаниями, поэтому вы можете попробовать следующее:

import { fromPromise } from 'rxjs/observable/fromPromise';

@Injectable()
export class AuthInterceptor implements HttpInterceptor{

    constructor(private authService: AuthService){}

    intercept(req: HttpRequest<any>, next: HttpHandler) : Observable<HttpEvent<any>>{
        return fromPromise(this.authService.getToken())
              .switchMap(token => {
                   const headers = req.headers
                            .set('Authorization', 'Bearer ' + token)
                            .append('Content-Type', application/json');
                   const reqClone = req.clone({
                     headers 
                    });
                  return next.handle(reqClone);
             });
    }
}

Ответ 2

для RxJS 6+ Я обновил Jota.Toledo Ответ:

import { fromPromise } from 'rxjs/observable/fromPromise';

@Injectable()
export class AuthInterceptor implements HttpInterceptor{
constructor(private authService: AuthService){}
intercept(req: HttpRequest<any>, next: HttpHandler) : Observable<HttpEvent<any>>{
    return fromPromise(this.authService.getToken())
          .pipe(switchMap(token => {
               const headers = req.headers
                        .set('Authorization', 'Bearer ' + token)
                        .append('Content-Type', 'application/json');
               const reqClone = req.clone({
                 headers 
                });
              return next.handle(reqClone);
         }));
 }  
}

Ответ 3

Моя очередь (Спасибо Jota.Toledo и Capripio):

1) Переключатель "fromPromise" на "from" → fromPromise не существует для типа Observable

2) Исправить цитату 'application/json'

import { Observable, from } from 'rxjs';
import { switchMap } from 'rxjs/operators';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private authService: AuthService){}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

      return from(this.authService.getToken()).pipe(
        switchMap(token => {
            const headers = req.headers
                .set('Authorization', 'Bearer ' + token)
                .append('Content-Type', 'application/json');
            const reqClone = req.clone({
                headers
            });
            return next.handle(reqClone);
        }));
   }
}

Моя версия RxJs: "6.2.2" Надеюсь, это помогло!