在Node.js中获取计时器ID

问题描述

我在NodeJS应用程序中有一个简单的服务器端计时器,用于通过套接字向客户端发送一些数据。如何设法将Timer ID发送给客户端,以便可以从客户端停止它?

我试图在套接字有效负载中传递返回的类,但出现错误“超出了最大调用堆栈大小。”

socket.on('start',() => {
const timerID = setInterval(()=>{
   socket.emit('data',someData)
   },3000)
socket.emit('ID',timerId)
}

还尝试映射类符号,但没有任何效果

const array = Object.getownPropertySymbols(timerID);

array.map((symbol) => {
clearInterval(timerID[symbol]);
 });

在NodeJS文档中找到以下内容

timeout[Symbol.toPrimitive]"()

返回:可用于引用此超时的数字

但是它也不起作用。

解决方法

客户端无法停止您的timerID,并且在nodejs中,timerID也不是简单的整数,也不是可以字符串化的内容,因此无法有效地发送给客户端。

您可以创建自己的整数标识符,该整数标识符映射到实际的timerID,将其发送给客户端,然后客户端可以向服务器发送回一条消息,它希望取消计时器X。您将在地图中查找timerX ,找到真正的timerID并停止计时器。

const timerMap = new Map();
const timerCntr = 0;

socket.on('start',() => {
    const timerID = setInterval(()=>{
        socket.emit('data',someData)
    },3000);

    // create an integer reference for the timer
    // save a mapping between the integer reference and the actual timerID
    // in a server-side Map object
    const externalTimerID = timerCntr++;
    timerMap.set(externalTimerID,timerID);
    socket.emit('ID',externalTimerID);
}

// when client wants to stop the timer
socket.on('stop',externalTimerID => {
    let timerID = timerMap.get(externalTimerID);
    clearInterval(timerID);

    // remove externalTimerID from the Map so we don't leak memory  
    timerMap.delete(externalTimerID);
});

从节点v14.9.0开始,您可以获得定时器ID的整数版本,它将代替实际的timerID对象。

socket.on('start',3000);

    socket.emit('ID',timerID[Symbol.toPrimitive]());
}

// when client wants to stop the timer
socket.on('stop',externalTimerID => {
    clearInterval(externalTimerID );
});

这是一个示例nodejs应用程序,我在其中验证了timerID[Symbol.toPrimitive]()是一个数字,并将替代timerID对象。

const timerID = setInterval(() => {
    console.log(`hi`);
},500);

const integerID = timerID[Symbol.toPrimitive]();

console.log(typeof integerID,integerID);    // shows it is an integer 

setTimeout(() => {
    console.log("clearing Interval with integerID");
    clearInterval(integerID);
},2000);