【问题标题】:How can I access attribute from service method in Angular?如何从 Angular 中的服务方法访问属性?
【发布时间】:2019-04-28 23:25:21
【问题描述】:

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

{
    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() 方法访问它。

我只想让该方法中的令牌可以访问,以便我可以发出请求。

【问题讨论】:

  • 猜猜当你发送查询时,getToken 还没有完成,此时令牌未定义
  • 您应该考虑查看诸如 switchMap 之类的运算符,以按照所需顺序将这些调用“链接”在一起,并将逻辑移出构造函数。

标签: angular typescript


【解决方案1】:

由于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 Interceptor

1.) 登录后,通常它会给你令牌。将该令牌存储在您的本地存储中

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 {}

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2014-02-01
      • 1970-01-01
      • 2014-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多