首页 > 解决方案 > 在角度 7 中使用装饰器时 rxjs 流中断

问题描述

错误e1:You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

代码

// interceptor
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
  constructor(private auth: AuthService) { }
@delayForToken()
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    //code to augment token to request
    return next.handle(req);
  }
}
//..



// decorator
export function delayForToken(observableName: string) {
  let auth: AuthService;
  return (target, key, descriptor) => {
    if (descriptor === undefined) {
      descriptor = Object.getOwnPropertyDescriptor(target, key);
    }
    const om = descriptor.value;
    descriptor.value = function (...args) {
      auth = (!auth) ? injector.get(AuthService) : auth;
      const ags = args;
      const ths = this;
      return auth.onToken().pipe(take(1)).subscribe(() => {
        return om.apply(ths, ags);
      });
    };
    return descriptor;
  };
}
//..


//following is slightly irrelevant, adding them for completeness
//AuthService
private tokenSub = new ReplaySubject<string>(1);
constructor(private afAuth: AngularFireAuth){
  this.afAuth.idToken.subscribe((tok: string) => {
    this.tokenSub.next(tok);
  }
}
public onToken(): Observable<string> {
  return this.tokenSub.asObservable();
}
//..


//app.module
providers: [
  { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }]
//..


//component
this.rest.hitserver('param1').subscribe((response: RspType[]) => {
  this.rsps = response;
}, (error) => { console.log('e1:' + error); }, () => { });
//..


//app.module
providers: [
  { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }]

意图:我正在尝试延迟 http 请求,直到我获得 idToken 设置,以便我可以将它增加到请求中。

更新:最终只在组件中使用注释,在拦截器中重复了逻辑switchMap(感谢Fan Cheung):

// @delayForToken() - Removed this annotation
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  if (this.auth.tok) {
    return next.handle(this.addTokenToReq(req, this.auth.tok));
  }
  return this.auth.onToken().pipe(take(1), switchMap((token: string) => {
    return next.handle(this.addTokenToReq(req, this.auth.tok));
  }));
  }
}

如果有办法让这个问题与装饰器一起工作,那么这个问题就会有答案。

标签: angularrxjsdecoratorrxjs6typescript-decorator

解决方案


推荐阅读