我有一个类作为服务器的客户端(通过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);
}
}
答案 0 :(得分:2)
您可以使用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();
答案 1 :(得分:1)
这就是事情:你永远不会达到对象“应该”被垃圾收集的点,因为你定义的setInterval
持有对该对象的引用(在你的上下文中,为{{ 1}})永远。您将需要一些额外的逻辑来确定是否仍需要运行它。
我推荐的是,这是一个简单的方法,因为你已经定义了this
,就是在那里放一些逻辑来监控是否有人在一段时间内确实要求延迟。如果最近运行了getter,请继续进行轮询。如果没有,请删除间隔。
如果您定义get Latency()
,那么如果您发现延迟最近没有被ping过,那么您可以这样做更容易,您可以等到重新计算延迟。
我没有运行这个,但是我想用它来说明这个想法:
async getLatency()
另外,您可能要考虑不使用// 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
。间隔的问题在于它基于自己的时钟。它不会考虑完成ping所需的时间。例如,如果你每秒轮询一次,但是完成ping需要500ms,那就没关系,但是如果ping需要2000ms,那么你的ping实际上会出现故障。看起来你的ping速度要慢得多,因为你收到ping的返回时间超过了最近运行速度快的ping。最好做一个setTimeout
,而不只是在最后一个完成之后运行。