【问题标题】:angular 4 service constructor issuesangular 4服务构造函数问题
【发布时间】:2018-03-23 08:31:33
【问题描述】:

我的身份验证服务有问题。如果我在构造函数中发出 http 请求,它会被调用 259 次。 如果我删除 http 调用,它会被调用一次。我使用共享模块来提供该服务的唯一实例。

Angular 版本:4.4.4

Console print

这是我的共享模块:

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);
      }
    );
   }
  }

谢谢!

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

@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);

  }
}

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

最终编辑: 我想出了如何在不进行无限循环的情况下从我的 authService 获取令牌。 问题是我用来为每个请求添加令牌到授权标头的 HttpInterceptor。 在我的 AuthService 构造函数中,我调用了发出 http 请求的登录方法。 LOOP: INTERCEPTOR => AUTH SERVICE => HTTP CLIENT 和 INTERCEPTOR

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

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);
  }

也许可以帮助遇到同样问题的人。 PS:检查后需要调用喷油器

感谢您的帮助!

【问题讨论】:

  • “ES6 类(或本例中的 TypeScript)上的构造方法是类本身的特性,而不是 Angular 特性”:toddmotto.com/angular-constructor-ngoninit-lifecycle-hook 考虑使用 constructor 主要用于依赖注入,请改用ngOnInit作为您的逻辑
  • ngOnInit 未在服务上调用...

标签: javascript angular angular-httpclient


【解决方案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]
})

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

【讨论】:

  • 这不行..是一回事..你试过在里面发出http请求吗?我需要声明的http客户端?
猜你喜欢
  • 2017-10-30
  • 1970-01-01
  • 2017-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多