在动态实例化的Angular2服务中处置observable

时间:2016-07-22 16:51:52

标签: angular

我有一个Angular2服务,它为每个用户会话实例化一次 - 指定为顶级用户组件的提供者。该服务创建了一个observable,可以为该特定用户驱动一些后台处理。

这会泄漏内存吗?有没有办法知道实例化服务何时“完成”,以便我可以处置observable?我需要这样做吗?

以下是一些示例代码:

export class UserAppModel {

  constructor(
    private requestQueue: RequestQueue
  ) {
    Observable.interval(1000).subscribe(() => {
      this.requestQueue.enqueue(aRequest);
    });

}

换句话说,当用户会话正在进行时,我想每秒排队一次特定请求。

UserAppModel在顶级登录(会话)页面中“提供”为

@Component...
  providers: [UserAppModel]
)
export class SessionFrontPageComponent {
}

因此,您可以看到此流未被ngOnDestroy上取消订阅的组件使用。我想另一种问这个问题的方法是,UserAppModel是否在该组件的providers中列出时被实例化,然后在该组件“离开”时以某种方式被销毁?即使是这样,我怎么知道这样才能处理可观察的流?

2 个答案:

答案 0 :(得分:5)

基本上有两种情况:

  1. 您只能在模板中使用async管道来使用可观察数据。在这种情况下,Angular会处理订阅,并在销毁组件时取消订阅。这里无事可做。

  2. 您可以在代码中手动订阅,方法是在该observable上调用subscribe方法。在这种情况下,您应该在组件销毁时手动取消订阅。

  3. 要手动取消订阅,请使用ngOnDestroy生命周期挂钩:

    import {OnDestroy} from '@angular/core'
    @Component({...})
    class MyComponent implements OnDestory {
      // Component's code
      constructor(private myService: MyService) {
        this.subscription = myService.getData().subscribe(data => {...});
      }
    
    
      // Unsubscribe when the component is destroyed to avoid leaks.
      ngOnDestroy() {
        this.subscription.unsubscribe()
      }
    }
    

    在某些情况下,当它们自己触发finish信号时,你可以放弃不取消订阅,但由于它通常是异步的,你不能确定它在组件被销毁之前发生,它是最好手动处理它。

    如果您对服务的可观察性是否结束感兴趣,可以使用带有三个参数的do运算符。

    @Injectable()
    export default class TestService {
    stream: Observable<number>;
    
    constructor() {
        this.stream = Observable.interval(1000)
        .do(
            data => console.log(data),
            error => console.log(error),
            () => console.log('FINISH') // On finish, all subscriptions will be disposed automatically
        );
    }
    

    同样适用于.subscribe。您可以使用组件中的第三个回调来记录流结束的时间。

    <强>更新

      

    我猜另一种提问的方式是UserAppModel   这是在列入提供者的情况下实例化的   组件,然后在该组件“离开”时以某种方式销毁?

    您的服务仍会每秒执行一次这些操作。您可以在订阅中尝试使用console.log内容来查看发生的情况。这就像在计划JS中设置超时一样。该函数将无限生存,并且可以访问服务实例,防止它被垃圾回收。

    作为旁注,我认为通过订阅observable来创建副作用是组件的角色,而不是服务。这就是他们首先拥有生命周期钩子的原因。您可以考虑仅从服务中公开observable,并在您的服务中管理订阅。这样你就不会遇到潜在的内存泄漏问题。

    export class UserAppModel {
      constructor(private requestQueue: RequestQueue) {}
      startFetchingData() {
          // As a bonus, if your requestQueue.enqueue is also an observable object,
          // you could just merge it together to even better control
          // the data (requests get cancelled when there's no active subscription)
          return Observable.interval(1000).mergeMap(() => {
              this.requestQueue.enqueue(aRequest);
          });
      }
    }
    
    class Component {
        ngOnInit() {
            this.subscription = this.userModel.startFetchingData().subscribe(data => {...})
        }
    
        ngOnDestroy() {
            this.subscription.unsubscribe();
        }
    }
    

答案 1 :(得分:3)

如果每个会话中只有一个(不确定如何定义会话但不重要)我没有看到任何可能的泄漏。 你应该确定只有一个, 和OnDestroy你可以完成observable(关闭所有订阅者)。