Angular 5将服务注入组件

时间:2018-03-13 20:17:53

标签: angular rxjs

我的身份验证服务+组件存在问题,因为每次加载auth组件时,服务似乎都会重新初始化。我应用程序中应该出现的流程是,应用程序启动时,根应用程序组件应发送一个登录请求,以检查当前会话是否经过身份验证。此登录请求正在从身份验证服务发送。 auth-service有一个主题广播一个布尔值,指示用户是否经过身份验证,具体取决于登录/注销操作的结果。

除了一种情况外,这种方法很有效。如果我在auth页面上启动应用程序,导航离开组件并返回到它,我无法从服务获得正确的身份验证状态(true / false)。打印时的字段(在服务中)由于某种原因未定义。为了调试,我甚至在ngOnInit函数中插入了console.logs,以查看是否正在重新初始化任何组件/服务,但没有。

以下是它现在看起来的代码示例,app.component.ts(根组件):

constructor(private requestService: RequestService,
              private authService: AuthService) {}

  ngOnInit() {
    console.log("App component init");
    this.requestService.get('http://localhost:8000/api/csrf/')
      .subscribe(
        success => {
          this.authService.login('', '');
        }
    );
  }

登录请求是第一次CSRF检查的结果,到目前为止效果很好。

auth.service.ts

@Injectable()
export class AuthService implements OnInit, OnDestroy {
  authenticated: boolean;
  authSubject: Subject<boolean>;

  constructor(private requestService: RequestService) {
    console.log("Auth service constructor");
    this.authSubject = new Subject<boolean>();
  }

  ngOnInit() {
    console.log("Auth service init");
    this.authSubject.subscribe(
      next => {
        this.authenticated = next;
      }
    );
  }

  login(username: string, password: string) {
    console.log("Auth service login");
    this.requestService.post(LOGIN_URL, { username: username, password: password })
      .subscribe(
        next => {
          this.authSubject.next(true);
          console.log("[AuthService] Success logging in.");
        },
        error => {
          console.log("[AuthService] Error logging in.");
        },
        () => {
          console.log("[AuthService] Auth service completed.");
        }
      );
  }

  logout() {
    this.requestService.post(LOGOUT_URL, {})
    .subscribe(
      next => {
        this.authSubject.next(false);
        console.log('[AuthService] Success logging out.');
      },
      error => {
        console.log("[AuthService] Error logging out.");
      },
      () => {
        console.log("[AuthService] Auth service completed.");
      });
  }

  isAuthenticated(): boolean {
    return this.authenticated;
  }

  ngOnDestroy() {
    console.log("Auth service destroyed");
    this.authSubject.unsubscribe();
  }
}

在这里,我们可以看到,我已经在构造函数中而不是在ngOnInit中实例化了Subject。这是因为当从app.component.ts触发登录时,尚未创建导致崩溃的主题。这仍然有用。

auth.component.ts

export class AuthComponent implements OnInit {
  authenticated: boolean;

  constructor(private authService: AuthService) { }

  ngOnInit() {
    console.log("Auth component init");
    this.authService.authSubject.subscribe(
      next => {
        this.authenticated = next;
      }
    );
    this.authenticated = this.authService.isAuthenticated();
    console.log(this.authenticated);
  }

  onLogin(form: NgForm) {
    const username = form.value.username;
    const password = form.value.password;
    this.authService.login(username, password);
  }

  onLogout() {
    this.authService.logout();
  }

所以,这就是我被困的地方。当我登录时,看到我成功获得响应并且authenticated = true。但是,当我离开auth视图然后返回到它时,从authService.isAuthenticated获取经过身份验证的值会让我回到&#34; undefined&#34;!服务在那里并且完好无损(我点击了ngOnDestroy服务,没有任何东西被解雇)所以我猜测有一个参考问题或什么,我只是无法在文档中找到任何帮助我的东西。

请告知。

2 个答案:

答案 0 :(得分:0)

尝试使用BehaviorSubject而不只是SubjectBehaviorSubject将在订阅之前广播最后一个值加上任何新值,而主题只会在您订阅后广播出任何新数据。

What is the difference between Subject and BehaviorSubject?

答案 1 :(得分:0)

问题在于没有为角度服务调用ngOnInit,因此在auth服务中从未激活订阅。当我将订阅移动到服务构造函数时,一切正常!