我有一个类,它充当服务器的客户端(通过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);
}
}发布于 2018-04-30 03:37:58
您可以使用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();发布于 2018-04-30 04:22:14
事情是这样的:您永远不会达到对象“应该”被垃圾回收的地步,因为您定义的setInterval永久地持有对该对象的引用(在您的上下文中,作为this)。您将需要一些额外的逻辑来确定是否仍需要运行它。
我推荐的是,这是一种简单的方法,因为你已经定义了你的get Latency(),就是在其中加入一些逻辑,以监控是否有人在一段时间内实际要求延迟。如果getter最近一直在运行,那么就继续轮询。如果没有,则删除间隔。
如果您定义了async getLatency(),那么可以让这件事变得更容易,这样,如果您检测到延迟最近没有被pinged,您可以等待等待,直到重新计算延迟。
我没有运行这段代码,但我将其包括在内是为了说明这个想法:
// 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所需的时间。例如,如果你每秒轮询一次,但是需要500ms来完成ping,这是可以的,但是如果需要2000ms来ping,那么你的ping实际上会变得无序。它可能看起来像是你有一个慢得多的ping,因为你收到的ping返回的时间比最近运行得快的ping花费的时间更长。更好的做法是做一个setTimeout,只在最后一个完成后运行。
https://stackoverflow.com/questions/50090440
复制相似问题