javascript - Get Timer ID in Node.js
问题描述
I have a simple server-side timer in NodeJS application to send some data with socket to client. How do I manage to send Timer ID to client so it can be stopped from a client side?
I tried to pass returned class in socket payload, but got an error "Max call stack size exceeded.
socket.on('start', () => {
const timerID = setInterval(()=>{
socket.emit('data',someData)
},3000)
socket.emit('ID',timerId)
}
Also tried to map over class symbols, but nothing works.
const array = Object.getOwnPropertySymbols(timerID);
array.map((symbol) => {
clearInterval(timerID[symbol]);
});
Found in NodeJS Documentation this:
timeout[Symbol.toPrimitive]"()
Returns: number that can be used to reference this timeout
But it also didn't work.
解决方案
The client cannot stop your timerID
and, in nodejs a timerID is not a simple integer either or something that can be stringified so it can't effectively be sent to the client.
You could create your own integer identifier that is mapped to the actual timerID, send that to the client and then the client could send the server back a message that it wishes to cancel timer X. You would look up timerX in your Map, find the real timerID and stop the timer.
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);
});
Starting with node v14.9.0, you can get an integer version of the timerID that will work as a substitute for the actual timerID object.
socket.on('start', () => {
const timerID = setInterval(()=>{
socket.emit('data', someData)
}, 3000);
socket.emit('ID', timerID[Symbol.toPrimitive]());
}
// when client wants to stop the timer
socket.on('stop', externalTimerID => {
clearInterval(externalTimerID );
});
Here's a sample nodejs app where I verified that timerID[Symbol.toPrimitive]()
is a number and will work as a substitute for the timerID object.
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);
推荐阅读
- c - 调整大小(更多)我是否正确解析浮点数?(使用 sscanf)
- php - PHP 错误 - 未能创建 COM 对象,未注册类
- angularjs - 根据Angular中的ng-view名称加载div
- javascript - 需要澄清 - 将争论传递给函数 - Javascript
- sql - 有多个相同的表或一个具有许多关系的表
- php - laravel 将 id 传递给控制器并在 url 中显示姓名和电话号码
- r - 如果前一行具有相同的值/字符串,则删除行(对于每个组)
- javascript - 量角器引导验证弹出消息
- php - php异常后的退出代码是什么?
- mysql - 查找仅管理预算 > 100 万美元的部门,但至少管理一个预算<500 万美元的部门的经理的姓名