打字稿-我无法使我的通用可观察解析器异步

时间:2019-02-27 16:51:36

标签: angular typescript rxjs

为了保持代码的整洁,我想创建一个通用方法来从可观察对象返回数据,一旦返回数据,该对象也将取消订阅。它返回数据,但是在代码移动后通常返回时为时已晚,这在登录页面上无法正常工作...

import { Observable, throwError } from "rxjs";
import { Type } from "@angular/compiler";

export async function resolveObseravableData<T>
  (obs: Observable<any>, classReference: { new (): T}) : T {

    let instance = new classReference();

    let obsRes = await obs.subscribe((data: T) => { instance = data; },
    (err: Error) => {   
       throwError(`Error in utility.functions.resolveObseravableData: ${err.message}`); })

    obsRes.unsubscribe();
    return instance;
}

当我向函数头添加异步时,我得到“类型T在ES5 / ES3中不是有效的异步函数返回类型”,因为它没有引用Promise兼容的构造函数值。”

我是angular / typescript的新手,我读到应取消订阅Observables以防止内存泄漏,但是下面的代码看起来很多,并且缺少将其转换为变量的方法,我对此一无所知退订。

this.authService.login(this.f.email.value, this.f.password.value).subscribe(
data => {
    if (data) {
        console.log('logged in ' + this.authService.currentUser.email);
        this.router.navigate([this.returnUrl]);
    } else {
        console.log('currrent user is null');
    }
}, 
err => {
    console.log('error on login' + err.message);
});

使用解析器替换以上内容:

if (resolveObseravableData(
  this.authService.login(this.f.email.value, this.f.password.value), Boolean)) {
    this.router.navigate([this.returnUrl]);
} else {
    console.log('currrent user is null');
};

这种可观察的分解器的想法只是一个坏主意,还是有一种更清洁的方式来做到这一点?

2 个答案:

答案 0 :(得分:1)

您始终可以为您可以取消订阅的订阅创建视图模型属性:

import { Subscription } from 'rxjs;

@Component({...})
export class YourComponent implements OnInit, OnDestroy {

  subscription: Subscription;

  constructor (
    private yourService: YourService,
  ) {}

  ngOnInit(): void {
    this.subscription = this.yourService.yourObservable$.subscribe(state => {...});
  }

  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }

}

作为替代方案,可以在组件销毁时使用“主题”退订。有关示例,请参见:https://medium.com/@stodge/ngrx-common-gotchas-8f59f541e47c

当然,| async管道也将为您退订。

答案 1 :(得分:0)

您是正确的,需要清理可观察的订阅,否则您可能会发生内存泄漏。但是在类似您的login示例的情况下,它们会自动清理自身:

如果可观察对象完成(成功或有错误),则订阅将自动释放,您无需担心。因此,在您调用登录服务的示例中,一个相当安全的假设是该服务返回一个可观察值,该可观察值只会产生一个值,然后才能完成。因此,一旦您观察到登录结果,订阅就会被处理,您就可以进行了。

清理订阅的建议确实适用于那些您订阅可观察对象的情况,该可观察对象可能返回许多值,并且您可能希望/需要在它们全部到达之前停止侦听。在这种情况下,另一个@Brandon的the answer提供了一种很好的退订模式。