Angular HTTP Interceptor 订阅 observable 然后返回 next.handle 但抛出 TypeError: You provided 'undefined' [英] Angular HTTP Interceptor subscribing to observable and then returning next.handle but throwing TypeError: You provided 'undefined'

本文介绍了Angular HTTP Interceptor 订阅 observable 然后返回 next.handle 但抛出 TypeError: You provided 'undefined'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 HTTP 拦截器,在每次请求之前,我检查访问令牌是否已过期,如果是,我从我的服务订阅 http.post 调用,然后订阅它,当我获得新的访问令牌时,我像这样调用 next.handle(request) :

I have a HTTP interceptor and before every request I check if the access token is expired, if it is, I subscribe to a http.post call from my service and then subscribe to it and when I get a new access token I call next.handle(request) like this:

        this.auth.refreshAccessToken().subscribe((token: string) => {
          this.auth.newAccessToken = token;
          request = request.clone({
            setHeaders: {
              Authorization: `Bearer ${token}`
            }
          });
          return next.handle(request);
        });

问题是它抛出 TypeError: You provided 'undefined' where a stream is expected.您可以提供 Observable、Promise、Array 或 Iterable.

这让我觉得我在那里调用 http.post 是错误的.

Which makes me think I'm making that http.post call wrong right there.

编辑 1:我还没有机会彻底测试这个,但到目前为止似乎一切正常.在返回整个地图之前我有一个 console.log 但它没有触发,但是,其他一切都有效,并且每次我获得新的访问令牌并且 DID 发生时,我都会在任何地方更新 currentUser/权限,因此出于所有意图和目的,它似乎工作,这是更新的代码:

EDIT 1: I haven't had the chance to test this thoroughly but so far it seems that everything works. I had a console.log before returning the whole map but it didn't fire, however, everything else worked and I update the currentUser everywhere/permissions everytime I get a new access token and that DID happen, so for all intents and purposes it seems to work, here's the updated code:

          mergeMap(token => {
            this.auth.newAccessToken = token;
            request = request.clone({
              setHeaders: {
                Authorization: `Bearer ${token}`
              }
            });
            return next.handle(request);
          })

推荐答案

你不会在拦截器内部 subscribe(),而是返回一个 Observable>.这可以通过使用 RxJS 可管道操作符 ('rxjs/operators') 来完成,例如 tap(用于设置 newAccessToken 等副作用)和 switchMapmergeMap 结合使用pipe(),返回一个 Observable> 类型的 observable 以满足 HttpInterceptor 接口:

You would not subscribe() inside the interceptor, instead you would return an Observable<HttpEvent<any>>. This can be done by utilizing RxJS pipeable operators ('rxjs/operators') such as tap (for side effects like setting newAccessToken) and switchMap or mergeMap in combination with pipe(), returning an observable of type Observable<HttpEvent<any>> to satisfy the HttpInterceptor interface:

import { Injectable } from '@angular/core';
import {
  HttpEvent, HttpInterceptor, HttpHandler, HttpRequest
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';
import { AuthService } from './auth.service';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private auth: AuthService) { }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return this.auth.refreshAccessToken().pipe(
      tap(token => this.auth.newAccessToken = token), // side effect to set token property on auth service
      switchMap(token => { // use transformation operator that maps to an Observable<T>
        const newRequest = request.clone({
          setHeaders: {
            Authorization: `Bearer ${token}`
          }
        });

        return next.handle(newRequest);
      })
    );
  }
}

这是一个示例.请查看日志以查看正在注销的关键信息.

Here is an example in action. Please check out the logs to see key information being logged out.

希望有帮助!

这篇关于Angular HTTP Interceptor 订阅 observable 然后返回 next.handle 但抛出 TypeError: You provided 'undefined'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆