在发送 GET 或 POST 请求之前获取访问令牌

get Access Token before sending GET or POST request

我正在尝试访问构造函数中的令牌,如下面的 utils.service.ts 文件:

utils.service.ts > 构造函数

storage.get('token').then((val) => {
  this.token = val;
  console.log("token: ", val);
});

我的所有 api get 和 post 请求都需要令牌。当我拨打如下电话时:

utils.service.ts

getDashboard() {
    if (this.dashboard) {
      return Promise.resolve(this.dashboard);
    }
    return new Promise(resolve => {
      this.http
        .get(globals.base_prod_api_url + "dashboard", {
          headers: {
            "Content-Type": globals.content_type,
            Authorization: "Bearer " + this.token
          }
        })
        .subscribe(
          data => {
            this.dashboard = data;
            resolve(this.dashboard);
          },
          error => {
            console.log(error);
            this.dashboard = error;
            return this.dashboard;
          }
        );
    });
  }

dashboard.page.ts

this.utilService.getDashboard().then(data => {
  this.dashboard_data = data;
});

甚至在从存储中检索令牌值之前就执行了获取请求。 如何才能先获取令牌然后再向服务器发出获取请求?

我认为你应该使用拦截器来做到这一点。

首先,您必须将其添加到您的 app.module.ts 提供商中:

  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HttpTokenInterceptor,
      multi: true
    },
    ...
  ],

然后拦截请求并将您的令牌添加到 headers :

import { Injectable, Inject } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
import { JwtService } from '../services/jwt.service';

@Injectable({
 providedIn: 'root'
})
export class HttpInterceptorService implements HttpInterceptor {
  constructor(
    private jwtService: JwtService,
  ) {}

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

  const headersConfig = {
    'Accept': 'application/json',
  };

  storage.get('token').then((token) => {
      headersConfig['Authorization'] = `Bearer ${token}`;
      return next.handle(request.clone({
         setHeaders: headersConfig
      }));
  });
}

更进一步,您可以使用拦截器来捕获错误:(例如 401 来处理刷新令牌)

return next
.handle(request.clone({
    setHeaders: headersConfig
}))
.pipe(
    catchError(err => {

        if (err.status === 401) {
            // token is no longer available, refresh it
        }

        return throwError(err);
    })
);

您可以在 utils.service.ts 中创建私有异步方法 如果令牌的值未定义并且 return 它会 git 令牌。 例如:

  async getToken(): Promise<string> {
    if(!this.token){
      this.token = await storage.get('token');
    }
    return this.token;
  }

并将其他方法标记为异步和 'await' headers object 中的令牌。

例如

async getData(){
   ....
      headers: {
            "Content-Type": '...',
            Authorization: "Bearer " + await this.getToken()
      }
   ....
}

如果我是你,我会使用 Observables 而不是 Promises。类似于 RXJS 6

import { from } from 'rxjs';

get authToken(): Observable<string> {
  return from(storage.get('token')))
}

sendRequest():Observable<ReturnedObject> {
  this.authToken.pipe(switchMap(token => {
    return this.http
      .get(globals.base_prod_api_url + "dashboard", {
        headers: {
          "Content-Type": globals.content_type,
          Authorization: "Bearer " + token
        }
      })
  }))
}

或者 ES6 Promises 装饰器:Async、Await 将从根本上简化您的代码。只是不记得通过 try/catch 块

捕获被拒绝的承诺