【问题标题】:Discord.js interval is not clearedDiscord.js 间隔未清除
【发布时间】:2021-05-22 21:27:39
【问题描述】:

我正在使用我的 Discord 机器人通过在会员进入语音频道时更新数据库来给他们钱。但是即使他们离开了语音频道,我的机器人仍然会运行这个功能来给他们更多的钱。虽然我用的是clearInterval,但是间隔并没有取消。

client.on('voiceStateUpdate', (oldState, newState) => {
  if (!oldState.channelID && newState.channelID) {
    oldState.member.roles.add("845279222590472253")

    var interval = setInterval(() => {
      db2.add(`para_${newState.member.user.id}`, 60)
    }, 5000);

  }
  else if (oldState.channelID && !newState.channelID) {
      oldState.member.roles.remove("845279222590472253");
      clearInterval(interval)
  }
});

【问题讨论】:

    标签: javascript node.js discord.js


    【解决方案1】:

    问题是,var 的作用域是函数,而变量 interval 只能在创建它的函数内部使用。

    在每个voiceStateUpdate 上,您都在调用定义新变量的回调函数。这意味着,如果有人连接,您将开始一个新的时间间隔,变量 interval 仅在该函数内可用。如果同一成员断开连接,则会使用新的回调函数和新的 (undefined) interval 变量触发新的 voiceStateUpdate 事件。

    查看下面的 sn-p:

    function gimmeMoney(oldState, newState) {
      if (!oldState && newState) {
        var interval = setInterval(() => console.log('Add money'), 2000)
        console.log('Interval started to add money', {
          interval
        })
      } else if (oldState && !newState) {
        console.log('Clearing', {
          interval
        })
        // as interval is undefined, you can't clear it
        clearInterval(interval)
      }
    }
    
    console.log('Connect to voice channel')
    gimmeMoney(false, true)
    console.log('Wait for 6 seconds before we disconnect...')
    
    let timeLeftBeforeClear = 6
    const countdown = setInterval(() => {
      timeLeftBeforeClear -= 1
      console.log()
    
      if (timeLeftBeforeClear <= 0) {
        clearInterval(countdown)
        console.log('Time to disconnect...')
        return gimmeMoney(true, false)
      }
    }, 1000)

    如果你运行上面的sn -p,你可以看到在你想清除区间的时候区间ID是未定义的,所以它什么也不做,区间一直运行。

    要解决这个问题,您需要将区间 ID 存储在函数之外。您可以将这些 ID 存储在对象、地图或 Discord Collection 中。如果使用集合,可以在集合中添加一个新的区间 ID,当有人连接时,以成员的 ID 作为键。当同一成员断开连接时,您可以使用他们的成员 ID get他们的间隔 ID。

    查看下面的工作代码:

    // create a new collection to store the interval IDs
    const intervals = new Discord.Collection();
    
    client.on('voiceStateUpdate', (oldState, newState) => {
      if (!oldState.channelID && newState.channelID) {
        oldState.member.roles.add('845279222590472253').catch(console.error);
    
        // set up a new interval and grab the returned ID
        const interval = setInterval(() => {
          db2.add(`para_${newState.member.user.id}`, 60);
        }, 5000);
        // add a new element in the collection with the member's ID as the key
        intervals.set(oldState.member.id, interval);
      } else if (oldState.channelID && !newState.channelID) {
        oldState.member.roles.remove('845279222590472253').catch(console.error);
        
        // get the interval ID from the collection by the member's ID
        const interval = intervals.get(oldState.member.id);
        clearInterval(interval);
        // don't forget to remove it from the collection too
        intervals.delete(oldState.member.id);
      }
    });
    

    【讨论】:

      猜你喜欢
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多