Angular HTTP Client在拦截器内返回null

use*_*svm 7 ionic2 ionic3 angular

在下面的代码中,我发布了两个代码在控制台中返回的示例.对于拦截器,我应该返回一个可观察的.我已将本地存储承诺转换为使用switchmap的可观察对象.我仍然使用这种方法返回null.我的observable包含在函数中,所以我应该得到一个null以外的值.谢谢!

Interceptor.js

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

accessToken: string; 
emptyToken: any;


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

//example

        this.storage.get('token').then((val) => {
             this.accessToken = val
            return console.log(this.accessToken, ' this is returning null value for token')
        })

//trying to return actual header
          return fromPromise(this.storage.get('token')).switchMap(access => {

            this.accessToken = access
            console.log(this.accessToken, ' this is returning null value for token')
            const authReq = req.clone({
                setHeaders: {
                Authorization: this.accessToken
                }
                });

                return next.handle(authReq)
           })
}
}
Run Code Online (Sandbox Code Playgroud)

我已经添加了下面更新的代码,请忽略上面的代码并仍然得到相同的结果.作为下面所述的答案之一,它们在所有假设中都是正确的.归结为将令牌置于登录observable内部.问题不在于拦截器,代码工作正常.我需要以某种方式获取我的异步值而不返回null.this.storage.ready()方法也给了我相同的结果.我的拦截器后调用了auth服务,因此我还没有生成任何令牌.我将如何首先调用我的身份验证服务?

login(userName: string, password: string, route: string = null): any {
     this.storage.set('tokens', 'able to retrieve this token value inside interceptor');

    this.logout(false);

    this.doLogin(userName, password)
      .subscribe(response => {

        let token:string = JSON.stringify(response.access_token);
        this.storage.set('token', token)

      }

      }
Run Code Online (Sandbox Code Playgroud)

interceptor.ts

get(url: string, options?: RequestOptionsArgs): Observable<Response> {
  return Observable.fromPromise(
    this.getRequestOptionArgs(options)
  ).mergeMap((options) => {
    return super.get(url, options)
  })
  }

private getRequestOptionArgs(options?: RequestOptionsArgs) {
    return this.storage.get('token').then((token) => {
      console.log(token, 'token for the get')
      if (options == null) {
        options = new RequestOptions();
      }

      if (options.headers == null) {
        options.headers = new Headers();
      }

      if (token !== null) {
        options.headers.append('Authorization', 'Bearer ' + token);
      }
      options.headers.append('Content-Type', 'application/json');

      return options;
    });
  }
Run Code Online (Sandbox Code Playgroud)

Dan*_*isp 2

我认为问题在于你StorageService正在返回null,而不是拦截器的问题。

存储服务使用 Promise,这意味着它只会发出一个值。如果您收到了null,那么我猜您还没有存储令牌。

您首先从哪里获得令牌?服务器?在这种情况下,第一个请求将没有令牌。

但是...您说过,当您localStorage直接(同步)访问时,您会得到一个值并且一切正常。所以我假设您已经存储了一个令牌。

查看离子存储的文档,看起来还有另一种可能性。存储有ready方法,所以可能存储还没有准备好。

您可以尝试这样的操作(未经测试),首先等待准备好的承诺解决,然后再尝试获取令牌:

import { Injectable } from '@angular/core';
import { HttpErrorResponse, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/observable/fromPromise';

@Injectable()
export class Interceptor implements HttpInterceptor {

    constructor (private storage: StorageService) {}

    intercept (request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // chain the ready promise with the get token promise
        return Observable.fromPromise(this.storage.ready().then(this.storage.get('token')))
            .mergeMap((token: string) => {

                const authReq = request.clone({
                    setHeaders: {
                        Authorization: token
                    }
                });

                return next.handle(authReq);

            });
    }
}
Run Code Online (Sandbox Code Playgroud)

只是一个猜测...