Javascript 对象不再被引用时的clearInterval?

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.

我有一个类充当服务器的客户端(通过WebSocket)。我想实现一个系统,定期ping服务器以确定延迟。但是,我担心如果我在类内部为此使用
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;
}