0
    const fetch = require('node-fetch');
    const config = require('./config.json');
    const config2 = require('./config2.json');

    function SendMessage(ChannelId, Authtoken, MessageToSend){
        fetch(`https://discord.com/api/v9/channels/${ChannelId}/messages`, {
          "headers": { /* ... */ },
          "body": `{"content":"${MessageToSend}","tts":false}`,
          "method": "POST"
        });
    };

    MessageLoop = async () => {
      for (let i = 0; i < 10; i++) { 
        await new Promise(resolve => {setTimeout(SendMessage, 5000, "1002639672528347206", "x", "iiiiii")
        resolve()
      })
        console.log(i)
      }
    }
    MessageLoop()

I have just started learning js, it is my first language, so bear with me here. Basically, SendMessage is a function that makes a post request with node-fetch. However, when I run this, it waits the 5000 ms, sends the request and then exits out of the program. It doesn't even console.log i or complete the for loop, and I have no idea why.

Konrad
  • 21,590
  • 4
  • 28
  • 64
Evil Twin
  • 1
  • 1
  • you cannot use promises with for loop, but you can with for-of loop (google it), and setTimeout only receives 2 arguments – Medet Tleukabiluly Jul 30 '22 at 14:11
  • 3
    First of all, you don't resolve the promise. – Mina Jul 30 '22 at 14:11
  • 6
    @MedetTleukabiluly you're wrong, in both points. – Thomas Jul 30 '22 at 14:13
  • 1
    @MedetTleukabiluly _"setTimeout only receives 2 arguments"_ - That's not true. The first argument is mandatory, but you can pass as many arguments as you want: https://developer.mozilla.org/en-US/docs/Web/API/setTimeout – Andreas Jul 30 '22 at 14:13
  • oh crap didn't know that – Medet Tleukabiluly Jul 30 '22 at 14:14
  • _"SendMessage is a function that makes a post request with node-fetch"_ - So you already have a `Promise` to await -> [What is the explicit promise construction antipattern and how do I avoid it?](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it) – Andreas Jul 30 '22 at 14:15
  • @EvilTwin, the problem is that you never `resolve()` (nor `reject()`) your promise, so the loop will wait forever in the first iteration for a Promise that never fulfills. – Thomas Jul 30 '22 at 14:16
  • @Thomas I added a resolve, but now, the loop does go through, however, it doesn't wait for each request to complete, could you tell me how I wait for each reqeuest to complete afterwhich it continues with the loop? – Evil Twin Jul 30 '22 at 14:21
  • That depends on the code in `SendMessage`. Please update your question to include all the relevant code. – Thomas Jul 30 '22 at 14:22
  • `await Promise.all([ ])` – Andreas Jul 30 '22 at 14:24
  • Do you do await on the "MessageLoop function"? – Chang Alex Jul 30 '22 at 14:25
  • @ChangAlex i do not – Evil Twin Jul 30 '22 at 14:28
  • @Thomas I cant send the function as it's larger than 555 characters. It's basically a fetch() with the arguments that I copied from my browser. – Evil Twin Jul 30 '22 at 14:30
  • @EvilTwin No, not in the comments, update the question. Press on [edit](https://stackoverflow.com/posts/73176303/edit) and update the snippet. – Thomas Jul 30 '22 at 14:31

1 Answers1

0
  1. added return to SendMessage(); it didn't return anything before. Now it returns the Promise from fetch() which you can await.

  2. I've also added a little utility function wait(). It's more convenient then dealing with setTimeout and callbacks when using async/await.

  3. in JS/TS we use camelCase Syntax for functions and variables. PascalCase is reserved for Classes. It may not seem like a big deal, but seeing a variable starting with an uppercase character gives the people that read your code a wrong/confusing impression about what that variable contains.

function sendMessage(channelId, authtoken, messageToSend) {
  return fetch(`https://discord.com/api/v9/channels/${channelId}/messages`, {
    "headers": { /* ... */ },
    "body": `{"content":"${messageToSend}","tts":false}`,
    "method": "POST"
  });
};

function wait(delay) {
  return new Promise(resolve => setTimeout(resolve, delay));
}

messageLoop = async() => {
  for (let i = 0; i < 10; i++) {
    await wait(5000);
    await sendMessage("1002639672528347206", "x", "iiiiii");
    console.log(i);
  }
}

messageLoop()

going back to your code, you could write

await new Promise(resolve => {
  setTimeout(() => {
    resolve(SendMessage("1002639672528347206", "x", "iiiiii"));
  }, 5000);
});

But as Andreas already pointed out in the comments, using new Promise when you don't have to is an antipattern.

Thomas
  • 11,958
  • 1
  • 14
  • 23