Javascript 对象不再被引用时的clearInterval?
我有一个类充当服务器的客户端(通过WebSocket)。我想实现一个系统,定期ping服务器以确定延迟。但是,我担心如果我在类内部为此使用Javascript 对象不再被引用时的clearInterval?,javascript,typescript,clearinterval,Javascript,Typescript,Clearinterval,我有一个类充当服务器的客户端(通过WebSocket)。我想实现一个系统,定期ping服务器以确定延迟。但是,我担心如果我在类内部为此使用setInterval,它会在对象应该被垃圾收集后继续尝试ping。我如何知道何时调用clearInterval 代码摘要: class WSClient extends EventEmitter { private latency: number; public get Latency(): number { return this.
setInterval
,它会在对象应该被垃圾收集后继续尝试ping。我如何知道何时调用clearInterval
代码摘要:
class WSClient extends EventEmitter
{
private latency: number;
public get Latency(): number
{ return this.latency; }
public async ping(): Promise<number>
{ ... }
public constructor(options)
{
super();
// Do constructor stuff
setInterval(() => this.ping().then(latency => this.latency = latency), 1000);
}
}
类WSClient扩展了EventEmitter
{
私有延迟:数字;
公共获取延迟():编号
{返回this.latency;}
公共异步ping():承诺
{ ... }
公共构造函数(选项)
{
超级();
//做构造器的事
setInterval(()=>this.ping().then(latency=>this.latency=latency),1000);
}
}
您可以使用setInterval()并将其保存到一个变量中,然后可以按如下方式访问该间隔:
class WSClient extends EventEmitter
{
private latency: number;
public get Latency(): number
{ return this.latency; }
public async ping(): Promise<number>
{ ... }
public constructor(options)
{
super();
// Do constructor stuff
this.interval = setInterval(() => this.ping()
.then(latency => this.latency = latency), 1000);
}
}
事情是这样的:您永远不会达到对象“应该”被垃圾收集的程度,因为您定义的
setInterval
永久地持有对该对象的引用(在您的上下文中,称为this
)。您将需要一些额外的逻辑来确定是否仍然需要运行它
我建议,这是一种简单的方法,因为您已经定义了get Latency()
,将一些逻辑放在其中,以监控是否有人在一段时间内实际要求延迟。如果getter最近运行过,请继续轮询。如果没有,请删除间隔
如果您定义了async getLatency()
,则可以更轻松地执行此操作,这样,如果您检测到延迟最近没有被ping,则可以等待延迟重新计算
我没有运行这个,但我将其包括在内以说明这个想法:
// ms to wait until cancelling the interval
const latencyTimeout = 200000;
// In your class
async getLatency(): number {
if (!this.latency) {
const started = Date.now();
const poller = setInterval(async () => {
if (Date.now() - started > latencyTimeout) {
clearInterval(poller);
this.latency = null;
}
this.latency = await this.ping();
}, 1000);
this.latency = await this.ping();
}
return this.latency;
}
作为一个旁白,您可能想考虑不使用<代码> SETIFATION< /COD>,而不是重复的<代码> SETTIMEOUT。时间间隔的问题在于它是基于自己的时钟。它不会考虑完成ping所需的时间。例如,如果你每秒钟进行一次轮询,但是需要500毫秒才能完成ping,这是可以的,但是如果需要2000毫秒才能完成ping,那么你的ping实际上会出问题。这可能看起来你的ping速度要慢得多,因为你收到的ping返回的时间比最近运行得快的ping返回的时间要长。最好使用
setTimeout
,而不是只在最后一个完成后运行。根据if(obj){}
@ScottMarcus有条件地使用递归的setTimeout()
,这是一个非常好的主意。因此,即使我在回调中引用该对象,也应该对其进行垃圾收集?(if(obj){…}
)我们需要查看您的代码结构才能回答这个问题。可能不是因为对象仍然被引用。也许您可以实现一个清除间隔的destroy
方法。@muecas这取决于所有这些代码是否都在一个调用上下文中。如果太长时间后失败,您应该调用,但如果失败太长,则取决于您的配置。
// ms to wait until cancelling the interval
const latencyTimeout = 200000;
// In your class
async getLatency(): number {
if (!this.latency) {
const started = Date.now();
const poller = setInterval(async () => {
if (Date.now() - started > latencyTimeout) {
clearInterval(poller);
this.latency = null;
}
this.latency = await this.ping();
}, 1000);
this.latency = await this.ping();
}
return this.latency;
}