gpt4 book ai didi

typescript - 如果主题超出范围时未取消订阅,订阅 rxjs 主题会导致内存泄漏吗?

转载 作者:行者123 更新时间:2023-12-04 14:39:43 29 4
gpt4 key购买 nike

在我的应用程序中,我有一些代表本地货币的对象,以及代表货币汇率的其他对象。
我的问题是,如果我的本地货币对象订阅货币对象上的单个主题以收到汇率变化的警报(但货币对象实际上并不保存订阅),然后单一货币实例定义所有这些订阅的主题是设置为 null,如果我没有对 50,000 个货币对象中的每一个都调用取消订阅,所有这些“订阅”会消失吗?
对于一个具体(简化)的例子,这个:

import { Subject } from 'rxjs'
interface MyChangeEvent {
oldValue : number;
newValue : number;
}
export class Currency {
rateSubject : Subject<MyChangeEvent>;
private _rate : number;
private _name : string;
constructor(name : string, rate : number) {
this.rateSubject = new Subject();
this._rate= rate;
this._name = name;
}
get rate() : number {
return this._rate;
}
set rate(v : number) {
let oldrate = this.rate;
this._rate = v;
let ce : MyChangeEvent
ce = {} as MyChangeEvent;
ce.newValue = v;
ce.oldValue = oldrate;
this.rateSubject.next(ce);
}
}


export class Money {
private _rate : number = 1;
private _localCurr : number = 0;

get dollarValue() {
return this._localCurr * this._rate;
}

constructor(localCurr : number, curr : Currency) {
this._localCurr = localCurr;
this._rate = curr.rate;
curr.rateSubject.subscribe((change)=>{
this._rate = change.newValue;
})
}
}

const test = function() {
let c = new Currency("USD", 1);
let m = new Money(500, c);
c.rate = .5;
c=null;
}
所以我的问题是,假设我的应用程序中有 50,000 个货币对象,然后我设置了 c=null就像这里的最后一行。我为所有这些货币对象设置的 50,000 个监听器是否保留在内存中的某个位置,当 Currency 对象超出范围时,它们是否都被垃圾回收了?

最佳答案

编辑
您也可以查看 RxJS: Why memory leaks occur when using a Subject .

我会说不会有内存泄漏。
这是基于我对内存泄漏实际发生的原因的理解。
通常这种问题发生在源是无限的(例如不会完成/错误,如组件使用的全局服务)。
例如,在 Angular 中,一种常见的模式是将应用范围内的服务注入(inject)到组件中,并订阅该服务公开的可观察属性之一。

class Service {
private usersSrc = new Subject();
users$ = this.usersSrc.asObservable();
}
然后你会在你的组件中这样做:
class FooComponent {
ngOnInit () {
this.subscription = this.service.users$.subscribe(() => {} /* callback */)
}
}
注意:这仅用于演示目的,因为您希望使用其他方法,这样您就不必手动订阅,例如异步管道
users$已订阅,因为 users$来自 usersSrc ,新创建的订阅者将被添加到主题的订阅者列表中。还有那个订阅者的 下一个回调将是 () => {}打回来。
现在当组件被销毁时(例如由于导航到另一条路线),如果你不做类似 this.subscription.unsubscribe() 的事情,该订阅者仍将是该订阅者列表的一部分。 unsubscribe方法将从该列表中删除该订阅者。
因此,下次创建组件时, ngOnInit已创建,一个 新订户将被添加,但如果您不使用 this.subscription.unsubscribe(),旧的仍然存在.

我会说将该源设置为 null 就足够了。
如果源恰好是 Subject ,您也可以使用 Subject.unsubscribe ,虽然它可能没有任何区别。
unsubscribe() {
this.isStopped = true;
this.closed = true;
this.observers = null!;
}

这将是一个简化版本。您可以将其粘贴到您的控制台中。
src = {
subscribers: [],
addSubscriber(cb) {
this.subscribers.push(cb);
return this.subscribers.length - 1
},
removeSubscriber(idx) {
this.subscribers.splice(idx, 1)
},
next (data) {
this.subscribers.forEach(cb => cb(data));
}
}

// the component
class Foo {

constructor () {
this.subIdx = src.addSubscriber(() => { console.log('foo') })
}

onDestroy () {
src.removeSubscriber(this.subIdx);
}
}

// usage

// creating a new component
foo = new Foo() // Foo {subIdx: 0}

// sending data to subscribers
src.next('test')

// destroying the component - without calling `onDestroy`
foo = null


src.next('test') // the subscribers is still there
VM506:18 foo

foo = new Foo() // registering a new instance - Foo {subIdx: 1}

src.next('test2')
foo
foo

foo.onDestroy()
src.next('test2')
foo

关于typescript - 如果主题超出范围时未取消订阅,订阅 rxjs 主题会导致内存泄漏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63257763/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com