【问题标题】:Angular 5 injecting services into componentsAngular 5 将服务注入组件
【发布时间】:2018-08-22 05:46:10
【问题描述】:

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

这很好用,除了一种情况。如果我在身份验证页面上启动应用程序,离开组件并返回到它,我无法从服务获得正确的身份验证状态(真/假)。出于某种原因打印状态未定义时的字段(在服务中)。为了调试,我什至在 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();
  }
}

我们开始吧,正如您在上面看到的,我已经诉诸于在构造函数中实例化 Subject,而不是在 ngOnInit 中。这是因为当从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();
  }

所以,这就是我卡住的地方。当我登录时,看到我成功获得了响应并且已验证 = true。但是,当我离开 auth 视图然后返回它时,从 authService.isAuthenticated 获取经过身份验证的值会让我返回“未定义”!该服务在那里并且完好无损(我为该服务使用了 ngOnDestroy,那里没有任何东西被触发)所以我猜测存在参考问题或其他什么,我只是在文档中找不到任何可以帮助我的东西。

请指教。

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

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

    What is the difference between Subject and BehaviorSubject?

    【讨论】:

    • 不回答我的问题,但行为主题可以帮助我在项目的其他部分,所以谢谢!
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2018-05-20
      • 2018-10-27
      • 1970-01-01
      • 2016-03-25
      • 1970-01-01
      • 2017-08-24
      • 2016-02-10
      • 2019-06-15
      相关资源
      最近更新 更多