如何从Angular的服务方法访问属性?

时间:2019-04-28 23:25:21

标签: angular typescript

我是Angular的新手,我试图将令牌从Spotify API传递到Angular中的服务方法,所以我有一个获取令牌并可以工作的端点,但是当我调用getQuery()方法时,输出标头的对象类似于:

{
    Authorization: Bearer undefined
}

因此,当我要发出请求时,由于我的访问令牌不正确,它会抛出401状态。

这是我的服务和构造方法的样子:

import { Injectable } from '@angular/core';
import { HttpClient,HttpHeaders } from '@angular/common/http';
import { map } from 'rxjs/operators';



@Injectable({
  providedIn: 'root'
})
export class SpotifyService {


  private token:string

  constructor(
    private http:HttpClient,

  ) {
    const clientId = 'my client id';
    const clientSecret = 'my client secret';
    this.getToken(clientId, clientSecret);

  }

这是我的getToken()方法的样子:

getToken(clientId:string, clientSecret:string){
    const urlRequest = `https://myendpoint/${clientId}/${clientSecret}`;
    this.http.get(urlRequest)
              .subscribe( (data:any) =>{
                this.token = data.access_token;
              });
  }

此时一切正常,但是当我从组件调用此服务并调用另一个服务方法时,构造函数似乎未执行,因为在此服务方法上出现了未定义的问题:

getQuery( query:string ){

    const url = `https://spotifyapi/${query}`;

    const headers = new HttpHeaders({
      'Authorization': `Bearer ${this.token}`
    });
    console.log(headers);
    return this.http.get(url,{headers});
  }

我使用console.log()来检查是否在getToken()中获取令牌,并且该令牌有效,但是似乎无法从getQuery()方法访问它。

我只想通过该方法访问令牌,以便发出请求。

2 个答案:

答案 0 :(得分:0)

好吧,我发现您尝试解决问题的方式存在一些问题。正如评论中指出的那样,在进行调用之前可能未获取令牌。 考虑进行以下更改

  1. 使用APP_INITIALIZER预先加载令牌,这样可以保证 在您的应用开始加载之前,您将拥有令牌-有一个 看着 - https://www.tektutorialshub.com/angular/angular-how-to-use-app-initializer/
  2. 如果每次调用都需要auth令牌,则不应添加 每个服务中的标头,请考虑在每个服务之前添加http拦截器以添加auth标头-https://medium.com/@ryanchenkie_40935/angular-authentication-using-the-http-client-and-http-interceptors-2f9d1540eb8

答案 1 :(得分:0)

  

由于this.http.get是一个异步呼叫,因此您应该等待直到呼叫结束。您可以根据实现方式来使用它:

@Injectable({ providedIn: 'root' })
export class SpotifyService {

   // Changing its type from a simple string to an Observable<string>
   private token$: Observable<string>;

   constructor(private http:HttpClient) {
     const clientId     = 'my client id';
     const clientSecret = 'my client secret';

     // Initialize the token
     this.token = this.getToken(clientId, clientSecret);
   }

   getToken(clientId:string, clientSecret:string): Observable<any> {
      const urlRequest = `https://myendpoint/${clientId}/${clientSecret}`;

      // Call the token api and get only its "access_token"
      return this.http.get(urlRequest).pipe(map(data => data.access_token));
   }

   getQuery( query:string ){

     const url = `https://spotifyapi/${query}`;

     // Subscribe to the token$ observable and assign the token on your headers
     this.token$.subscribe(token => {

       const headers = new HttpHeaders({ 'Authorization': `Bearer ${this.token}` });

       console.log(headers);

       return this.http.get(url, {headers});
     });

   }


}

  

另一种方法是使用 HTTP拦截器

1。)登录后,通常它将为您提供令牌。将该令牌存储在您的localStorage中

localStorage.setItem('token:id', token);

2。)创建auth.interceptor.ts

  

有了这个,每次您调用API时,它将自动插入标头

@Injectable({ providedIn: 'root' })
export class AuthInterceptor implements HttpInterceptor {

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

      const token = localStorage.getItem('token:id');

      if (token) {
         const cloned = req.clone({ headers: req.headers.set('Authorization', `Bearer ${token}`) });
         return next.handle(cloned);
      }
      else return next.handle(req);
  }
}

3。)将其导入您的AppModuleCoreModule(如果有)

@NgModule({
  imports: [],
  providers: [
    {
       provide: HTTP_INTERCEPTORS,
       useClass: AuthInterceptor,
       multi: true
    }
  ]
})
export class AppModule {}