【问题标题】:subscribe() to the same stream in 2 different components in Angular 2 with rxJs在 Angular 2 中使用 rxJs 订阅()到 2 个不同组件中的相同流
【发布时间】:2017-01-24 07:25:58
【问题描述】:

我正在尝试在 Ionic 2 Web 应用程序中设置登录名,并且我正在使用 observables。

我有一个带有登录方法的身份验证模块,它连接到远程数据库以记录用户;如果登录成功,我想将令牌(auth0)存储在本地存储中

所以这是在我的 auth.service.ts 中

login(user: any) {
    this.http
      .get(SERVER_URL, { user_data }, options)
      .map((response: Response) => response.json())
      .subscribe(
        data => this.authSuccess(data.jwt),
        err => this.handleError(err));
  }

所以,这本身就可以正常工作。现在我想使用登录屏幕,所以当用户提交数据时,如果登录成功应用程序将导航到主屏幕,否则将显示错误消息。

登录组件应该是这样的

loginUser(event) {
    return this.authService
      .login(event.user)
      .subscribe(
        data => navigate_to_main,
        err => display_error_and_stay_in_login);
  }

所以,我需要在服务中订阅登录方法,因为我只想在登录成功时存储令牌,但我还需要在 LoginComponent 中的 loginUser 方法中订阅,以便仅在登录成功时进行导航成功。

这是怎么做到的?也许我这样做的方式不对。

有人可以帮忙吗? 谢谢!

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

    auth.service.ts 可以返回 observable,允许登录组件进行订阅:

    login(user: any) {
        return this.http
          .get(SERVER_URL, { user_data }, options)
          .map((response: Response) => response.json())
          .do(
            data => this.authSuccess(data.jwt),
            err => this.handleError(err));
      }
    

    如果你需要从多个地方调用登录,你可以使用 .cache 避免重复请求:

    private _login$;
    
    loginOnce(user: any) {
        if (!this._login) {
            this._login = this.loginUser(user).cache();
        }
        return this._login;
    }
    

    组件的用法:

    this.authService.login(user).subscribe(response => ...)
    

    【讨论】:

    • 需要注意的是,您需要订阅才能消费数据。事实上,我最近注意到 HTTP 请求只有在有人订阅后才会执行。
    • @Luftzig。是的。这适用于任何可观察对象,而不仅仅是那些包含 HTTP 请求的对象。 Observables 就像函数。它们不会被执行,除非它们被调用,或者在 observables 的情况下被“订阅”。
    【解决方案2】:

    仅在您想要使用数据时订阅。您可以使用catch 处理服务中的错误。

    您必须将其导入 import 'rxjs/add/operator/catch';

    login(user: any) {
      return this.http
        .get(SERVER_URL, { user_data }, options)
        .map((response: Response) => {
          let data = response.json();
          this.authSuccess(data.jwt)
          return data;
        }).catch((err) => this.handleError(err) )
    }
    

    【讨论】:

      【解决方案3】:

      您可以通过在您的auth.service.ts 中进行以下更改来做到这一点:

      login(user: any) {
        return this.http
          .get(SERVER_URL, { user_data }, options)
          .map((response: Response) => {
            let data = response.json();
            this.authSuccess(data.jwt)
            return data;
          });
      }
      

      【讨论】:

      • 但是我错过了在我的 AuthService 中处理错误的机会,对吧?
      • 这行得通,但语义是错误的。 map 用于映射 observable 中的值,而不是用于产生副作用。 do 在语义上适用于副作用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-14
      • 2023-03-08
      • 2017-06-02
      • 2018-06-26
      • 1970-01-01
      • 2017-06-15
      • 2019-08-05
      相关资源
      最近更新 更多