我有一个类,它充当服务器的客户端(通过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);
}
}
您可以使用 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);
}
}
然后,当您需要时:
WSClient.interval.clearInterval();
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;
}
顺便说一句,您可能需要考虑不使用 setInterval
,而是使用重复setTimeout
。间隔的问题在于它基于自己的时钟。它不会考虑完成 ping 所需的时间。例如,如果您每秒轮询一次,但完成 ping 需要 500 毫秒,那没关系,但如果 ping 需要 2000 毫秒,那么您的 ping 实际上会出现故障。看起来您的 ping 速度要慢得多,因为您从比最近运行速度较快的 ping 中接收的 ping 值更长。最好做一个仅在最后一个完成后运行的setTimeout
。