角度4服务构造函数问题

时间:2017-10-11 15:22:35

标签: javascript angular angular-httpclient

我的authservice存在问题。如果我在构造函数中创建一个http请求,则会调用259次。 如果我删除了http调用,它会被调用一次。我使用共享模块来提供该服务的唯一实例。

Angular版本:4.4.4

Console print

这是我的sharedModule:



export const providers = [
  AuthService,
  DataStorageService,
];

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    HttpClientModule,
    ReactiveFormsModule,
    InfiniteScrollModule,
    TruncateModule
  ],
  declarations: [
    FooterComponent,
    PhotoListComponent,
    GalleryListComponent,
     ],
  exports: [
    FooterComponent,
    PhotoListComponent,
    GalleryListComponent,
    InfiniteScrollModule,

  ],
  providers: [
    
    ]})

export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [...providers]
    };
  }
}




我的AuthService:



@Injectable()
export class AuthService {

  public session: Subject<SessionModel> = new Subject<SessionModel>();
  private cachedSession: SessionModel = new SessionModel(null, null, false);
  private apiUrl = 'http://localhost:8080/Galleo/user/login';


   constructor(private cookieSrv: CookieService,
              private http: HttpClient) {
    console.log('constructor called');
    if (this.cookieSrv.get('system-g-unx-data')) {
      const cook = atob(this.cookieSrv.get('system-g-unx-data')).split('||');
      const username = cook[0];
      const password = cook[1];
      this.login(username, password);
    }
  }

  // login method, call REST API and store cookie into user Browser
  login(username: string, password: string) {

    const user: UserModel = new UserModel();
    user.userName = username;
    user.password = password;

    const headers = new HttpHeaders();
    headers.append('Content-Type', 'application/json');

    this.http.post<UserModel>(this.apiUrl, user, {observe: 'response', headers: headers}).subscribe(
      (response) => {
        console.dir(response);
        this.cachedSession.user = response.body;
        this.cachedSession.token = response.headers.get('Authorization');
        this.cachedSession.isAuthenticated = true;
        this.session.next(this.cachedSession);
        this.cookieSrv.put('system-g-unx-data', btoa(username + '||' + password));
      },
      (error) => {
        console.dir(error);
        this.session.next(null);
      }
    );
   }
  }
&#13;
&#13;
&#13;

谢谢!

编辑:我发现了问题。 来自AuthInterceptor。当我尝试获取授权令牌时,它会启动无限循环:

&#13;
&#13;
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  private authService: AuthService;
  constructor(private injector: Injector) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    console.log('Intercepted!', req);
    this.authService = this.injector.get(AuthService);

    const request = req.clone({
      setHeaders: {
        Authorization:  `${this.authService.getSession().token}`
      }
    });

    return next.handle(request);

  }
}
&#13;
&#13;
&#13;

现在如何在不使用注入器的情况下恢复Interceptor内的authService?

最终编辑: 我想出了如何从我的authService获取令牌而不进行无限循环。 问题是我用于为每个请求添加令牌到授权头的HttpInterceptor。 在我的AuthService构造函数中,我调用了生成http请求的login方法。 循环:INTERCEPTOR =&gt; AUTH SERVICE =&gt; HTTP CLIENT和再次INTERCEPTOR

所以,现在我在我的拦截器中进行一些检查,如:

&#13;
&#13;
Injectable()
export class AuthInterceptor implements HttpInterceptor {
  private authService: AuthService;
  constructor(private injector: Injector) {  }

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

    // If login method called skip and continue request
    if (req.url.includes('login')) {
      return next.handle(req);
    }

    // If request don't have the Authorization Header, add the token to the header
    if (!req.headers.has('Authorization')) {
      this.authService = this.injector.get(AuthService);
      const request = req.clone({
        setHeaders: {
          Authorization: `${this.authService.getSession().token}`
        }
      });
      return next.handle(request);
    }

    return next.handle(req);
  }
&#13;
&#13;
&#13;

也许可以帮助那些会遇到同样问题的人。 PS:检查后需要调用注入器

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

创建一个core / core.module.ts,在app.module.ts中导入一次

import { CommonModule } from '@angular/common';
import {
  ModuleWithProviders, NgModule,
  Optional, SkipSelf
} from '@angular/core';


import { AuthGuard } from '../guards/auth.guard';
import { AuthService } from '../services/auth.service';

@NgModule({
  imports: [CommonModule],
  declarations: [],
  exports: [],
  providers: [AuthGuard, AuthService]
})

export class CoreModule {

  constructor( @Optional() @SkipSelf() parentModule: CoreModule) {
    if (parentModule) {
      throw new Error(
        'CoreModule is already loaded. Import it in the AppModule only');
    }
  }

  static forRoot(): ModuleWithProviders {
    return {
      ngModule: CoreModule,
      providers: [
        AuthService,
        AuthGuard,
      ]
    };
  }
}

检查以确保仅加载一次。

app.module.ts

import {CoreModule} from './core/core.module';

@NgModule({
  declarations: [
  ],
  imports: [
    CoreModule.forRoot(),
  ],
  providers: [

  ],
  bootstrap: [AppComponent]
})

在“核心模块”下的文档中引用它作为单例#34; https://angular.io/guide/ngmodule