【问题标题】:How to send discord messages after waiting 1 second等待1秒后如何发送不和谐消息
【发布时间】:2025-12-14 16:55:02
【问题描述】:
if (msg.content.toLowerCase() === "!start") {
    var gov = setInterval(go, 1000);
    var onev = setInterval(one, 1000);
    var twov = setInterval(two, 1000);
    function two(msg) {
        msg.channel.send("https://i.imgur.com/JZOCg5l.png ");
    }
    function one(msg) {
        msg.channel.send("https://i.imgur.com/gTK3Vhn.png ");
    }
    function go(msg) {
        msg.channel.send("https://i.imgur.com/3iVfYIR.png ");
    }
    function two(msg) { }
    function one(msg) { }
    function go(msg) { }
    msg.channel.sendFile("https://i.imgur.com/kOoyoZQ.png ").then(onev).then(twov).then(gov);
}

这是一个非常烦人的任务。我需要大约一秒钟的时间发送这些图像。
当前框架不断给我以下错误:

C:\Users\maver\Documents\TestBot\testlev.js:197                                                                                  
msg.channel.sendFile("https://i.imgur.com/3iVfYIR.png ");                                                                
    ^                                                                                                                                                                                                                         
TypeError: Cannot read property 'channel' of undefined at Timeout.three [as _onTimeout] 
(C:\Users\maver\Documents\TestBot\testlev.js:197:17)                                
at ontimeout (timers.js:478:11)                                                                                      
at tryOnTimeout (timers.js:302:5)                                                                                    
at Timer.listOnTimeout (timers.js:262:5)   

我已经尝试了多种不同的方法,并且准备认输。

【问题讨论】:

    标签: javascript discord.js


    【解决方案1】:

    你的语法有点不对劲。当您执行function two(msg){... 时,您实际上是在告诉函数您将向它传递一个新变量,并且您想要那个名为msg 的变量。因此,msg(在您的函数的上下文中)未定义。当您从 setInterval() 调用函数时,您必须传入 msg

    有两种方法可以将msg 绑定到您的函数。我个人喜欢的方式是这样的:

    //...
    var gov = setInterval(go.bind(null, msg), 1000);
    var onev = setInterval(one.bind(null, msg), 1000);
    var twov = setInterval(two.bind(null, msg), 1000);
    //...
    

    .bind() 函数分配参数的值。调用函数的第一个参数是bind() 的第二个参数。 bind() 的第一个参数应该是函数内部this 的值。

    另一种方法是使用匿名函数

    //...
    var gov = setInterval(function(){go(msg)}, 1000);
    var onev = setInterval(function(){one(msg)}, 1000);
    var twov = setInterval(function(){two(msg)}, 1000);
    //...
    

    另请注意,setInterval() 会在每个周期重复一次函数调用。您可能正在寻找setTimeout(),它只会在延迟后触发一次函数。

    【讨论】:

    • 谢谢!机器人现在根据需要发送图像。不幸的是,即使有 10000 毫秒的延迟,图像仍然紧随其后(第一个除外)。我有机会解决这个问题吗?
    【解决方案2】:

    当你使用 setInterval 时,你应该知道它会调用函数,但不会提供任何参数给它(甚至this)。解决它的一种方法是使用绑定:

    setInterval(go.bind(null, msg), 1000)
    

    这会起作用,因为bind() 将创建一个新函数,其中参数“预先神奇地设置”。

    在这种情况下,另一种选择是简单地不在三个函数中重新声明 msg - 在这种情况下,javascript 将尝试从外部作用域中查找 msg,它存在:

    function two() {
        msg.channel.send("https://i.imgur.com/JZOCg5l.png ");
    }
    

    第三,你不应该使用setInterval,而应该使用setTimeout,它只会调用一次函数。

    您遇到的第四个问题是时间问题。首先,所有三个 setTimeout 调用同时发生,因此所有三个函数都将在一秒钟内调用(1000 毫秒后)。一个简单的解决方法就是:

    setTimeout(go, 1000);
    setTimeout(one, 2000);
    setTimeout(two, 3000);
    

    但是,这将完全忽略发送每条消息所需的时间(这可能是您想要的,也可能不是您想要的)。如果您想在上一条消息发送后等待一秒钟,那么您必须执行以下操作:

    msg.channel.sendFile("https://i.imgur.com/kOoyoZQ.png ").then(function() {
        setTimeout(go, 1000);
    });
    
    function go() {
        msg.channel.send("https://i.imgur.com/3iVfYIR.png").then(function() {
            setTimeout(one, 1000);
        });
    }
    
    // etc
    

    这将非常乏味,因为所有功能看起来都非常相似。所以更好的方法是创建一个消息列表,然后使用一个函数来发送所有消息:

    var msgs = [
        "https://i.imgur.com/kOoyoZQ.png",
        "https://i.imgur.com/JZOCg5l.png",
        "https://i.imgur.com/gTK3Vhn.png",
        "https://i.imgur.com/3iVfYIR.png" 
    ];
    
    function sendMsgs(msgs, delay) {
        if (msgs.length < 1) return; // we're done
        var remain = msgs.slice(1);
        var sendRemain = sendMsgs.bind(null, remain, delay);
        msg.channel.send(msgs[0]).then(function() {
            setTimeout(sendRemain, delay);
        });
    }
    
    sendMsgs(msgs, 1000);
    

    【讨论】:

      【解决方案3】:

      您的代码会立即执行,因为您必须维护您正在使用的承诺的值并没有正确使用。 你可以这样做:

      if (msg.content.toLowerCase() === "!start") {
          var urls = ["https://i.imgur.com/kOoyoZQ.png",
          "https://i.imgur.com/JZOCg5l.png",
          "https://i.imgur.com/gTK3Vhn.png",
          "https://i.imgur.com/3iVfYIR.png" ];
          function gov(urls){
          for(let k=0; k<urls.length;k++){
                 setTimeout(function() { msg.channel.send(k); },k*1000)
          }
          }
          gov(urls);
          }
      

      【讨论】:

        最近更新 更多