问题描述
我在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);