【问题标题】:Get Timer ID in Node.js在 Node.js 中获取计时器 ID
【发布时间】:2020-12-27 06:22:41
【问题描述】:

我在 NodeJS 应用程序中有一个简单的服务器端计时器,可以通过套接字向客户端发送一些数据。如何设法将计时器 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]"()

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

但它也没有工作。

【问题讨论】:

  • 您的第一个 sn-p 似乎是这样做的方式 - 调用堆栈大小的超出(通常是由于无限递归)可能是由于您的代码中的其他地方(大概与如何客户端正在响应这些消息?)

标签: javascript node.js timer settimeout setinterval


【解决方案1】:

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

您可以创建自己的整数标识符,该标识符映射到实际的 timerID,将其发送给客户端,然后客户端可以向服务器发送一条希望取消定时器 X 的消息。您可以在 Map 中查找 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 开始,您可以获得一个整数版本的 timerID,它可以替代实际的 timerID 对象。

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 );
});

这是一个示例 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);

【讨论】:

  • 感谢您的回答!这似乎是唯一的选择
  • @ViacheslavZahorodnyi - 在最新版本的 node.js 中,您可以使用代码 timerID[Symbol.toPrimitive]() 获取计时器的整数引用。升级到最新版本的 node.js 后,我在一个测试应用程序中尝试了它,它确实有效。请参阅我添加到答案中的示例。
  • 感谢您的帮助!
猜你喜欢
  • 2017-05-12
  • 1970-01-01
  • 1970-01-01
  • 2013-01-29
  • 2016-06-19
  • 2014-04-03
  • 2018-05-25
  • 1970-01-01
  • 2010-09-14
相关资源
最近更新 更多