Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
442 views
in Technique[技术] by (71.8m points)

angular - 如果未在内部保存(例如在类变量中),为什么不收集Observable的原因(Why Observable is not collected if not saved internally, e.g. in a class variable)

The code below creates Observable that passes current Date every second.

(下面的代码创建了Observable ,它每秒传递一次当前的Date 。)

From the code below I see that Observable<Date> is returned from the ObservableService & subscribed right away in AppComponent .

(从下面的代码中,我看到Observable<Date>是从ObservableService返回的,并立即在AppComponent订阅。)

Although Observable<Date> was not saved in AppComponent as a class internal variable, the app continues to receive notifications and the returned Observable<Date> is not collected by the GC.

(尽管Observable<Date>并未作为类内部变量保存在AppComponent中,但该应用程序继续接收通知,并且GC未收集返回的Observable<Date> 。)

My question is why it is so, why Observable<Date> was not collected/removed when no object is referencing or capturing it?

(我的问题是为什么会这样,为什么没有对象引用或捕获时没有收集/删除Observable<Date> ?)

My main assumption here is that closure in AppComponent : data => this.currentTime = data captures this ( AppComponent ) but not vise versa.

(我这里的主要假设是AppComponent中的闭包: data => this.currentTime = data捕获了此( AppComponent ),反之则不然。)

So as Observable<Date> is not captured in AppComponent , Observable<Date> should be removed soon after creation.

(因此,作为Observable<Date>不在捕捉AppComponentObservable<Date>应创建不久后删除。)

However it does not happen.

(但是它不会发生。)

Again, what is the reason for this?

(同样,这是什么原因呢?)

observable.service.ts

(observable.service.ts)

import { Observable, interval } from 'rxjs';

export class ObservableService {

  createObservableService(): Observable<Date> {
    return new Observable(
      observer => {
        interval(1000)
          .subscribe((_) => observer.next(new Date()));
      }
    );
  }
}

app.component.ts

(app.component.ts)

import { Component } from "@angular/core";
import { ObservableService } from "./observable.service";

@Component({
  selector: 'app-root',
  providers: [ ObservableService ],
  template: `<h1>Custom observable service</h1>
       Current time: {{currentTime | date: 'mediumTime'}}
  `})
export class AppComponent {

  currentTime: Date;

  constructor(private observableService: ObservableService) {
    this.observableService.createObservableService()
      .subscribe( data => this.currentTime = data );
  }
}

app.module.ts

(app.module.ts)

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ObservableService } from "./observable.service";

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [ObservableService],
  bootstrap: [AppComponent]
})
export class AppModule { }
  ask by Ievgen Gavrysh translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Good question.

(好问题。)

The thing is that when you have infinite value subscriptions, then you need to unsubscribe to avoid memory leaks.

(问题是,当您具有无限值订阅时,则需要取消订阅以避免内存泄漏。)

There is an answer here , that is quite relevant to the topic at hand that discusses when you need to unsubscribe from event.

(这里有一个答案 ,与您讨论何时需要退订事件的手头话题非常相关。)

Key takeaway: The subscription lifecycle is not embedded in the lifecycle of the component.

(关键要点:订阅生命周期未嵌入组件的生命周期中。)

This makes sense if you think of that the subscription could still be referenced in some other framework related code, even if it's not in ours.

(如果您认为仍可以在其他一些框架相关的代码中引用该订阅(即使它不在我们的代码中),则这是有道理的。)

Check this link from tha angular docs , which unsubscribes even when the subscription is created in the same component:

(从tha docs中检查此链接 ,即使在同一组件中创建订阅, 该链接也会取消订阅:)

  ngOnDestroy() {
    // prevent memory leak when component destroyed
    this.subscription.unsubscribe();
  }

Notice that this example captures the subscription and unsubscribe() when the AstronautComponent is destroyed.

(注意,此示例在销毁AstronautComponent时捕获了subscription和unsubscribe()。)

This is a memory-leak guard step.

(这是内存泄漏保护措施。)

There is no actual risk in this app because the lifetime of a AstronautComponent is the same as the lifetime of the app itself.

(此应用程序没有实际风险,因为AstronautComponent的生存期与应用程序本身的生存期相同。)

That would not always be true in a more complex application.

(在更复杂的应用程序中,并非总是如此。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...