删除仅使用一次的 observable 订阅的正确时间

The right time to remove subscription for observable that is only used once

我有以下登录功能,我只想使用一次登录,而不是永远坐在那里监听数据。 所以我正在寻找合适的时间调用取消订阅方法。 目前,我在得到结果或错误后立即调用取消订阅方法。这是有道理的,因为不再需要 observable。

但是...如果我的网速非常慢会发生什么,这就是会发生什么。

代码执行 observable 并等待数据从 firebase 返回(为了论证,说 1 分钟)。 在这个等待期间,假设有人在firebase中修改了这个条目,我相信firebase会认为,"hey someone is still listening and there is a change, so I better emmit the update to this person"

所以在这一点上,我会等待两组数据回来,第一个和更新的。

那么我会从控制台打印出两个数据还是不会发生这种情况?

onLogin() {
    // loginWithEmailPassword returns firebase.promise<AuthState>
    this.userService.loginWithEmailPassword(this.loginForm.value.email, this.loginForm.value.password)
    .then(data => {

        // if the user is logged in, go and retreive user information
        // getUserInformation returns Observable<any>
        let subscription_getUserInformation = this.userService.getUserInformation(data.uid)
        .subscribe(result => {

            // user information received
            console.log(result)

            // remove Subscription
            subscription_getUserInformation.unsubscribe();

        }, error => {
            // something went wrong
            subscription_getUserInformation.unsubscribe();
        })

    }, error => {
        // something went wrong
    });
}

您的订阅者只会收到一次通知,因为您正在订阅者的 next 功能中取消订阅。

但是,代码比它需要的更复杂,因为只要可观察对象完成或出错,订阅者就会自动取消订阅。

如果你只想要一个可观察对象的第一个发射值,你可以使用 first operator (which is equivalient to take(1)):

import 'rxjs/add/operator/first';

onLogin() {
  this.userService
    .loginWithEmailPassword(
      this.loginForm.value.email,
      this.loginForm.value.password
    )
    .then(data => this.userService
      .getUserInformation(data.uid)
      .first()
      .subscribe(
        result => { console.log(result); },
        error => { console.log(error); }
      )
    )
    .catch(error => { console.log(error); });
}

使用该运算符将确保组合的可观察对象在第一个发出值后完成,此时订阅者将自动取消订阅 - 因此不需要显式 unsubscription/clean up。