2
votes

Premise: I am far from a coding master, though not a complete novice, but am new to JavaScript and Discord. I've looked around and asked someone about this problem but to no avail, so any help would be much appreciated. (This is using Node.js, Discord.js)

I was starting to make a simple bot that would respond to your message, and I successfully did that. I then moved on to try to give it a switch statement to allow it to do different things based on what was said. Since I didn't know JavaScript I thought I'd start out simple and work my way up as I got familiar with it. However, this did not work so well.

Problem: After setting up a switch statement I found that it would only use the first instance of the switch statement that was first initialized. It would never swap to the next one. In case switch statements don't work quite the same as I have seen before I changed it to an if/else statement. Strangely enough, the same results occurred. I simplified it down to its basic logic to no avail.

// Run dotenv
require('dotenv').config();

const fs = require('fs');
const Discord = require('discord.js');
const client = new Discord.Client();

//Set Var
var testNumb = 0;


// Code Start
  console.log("Initial value" + testNumb);
  if(testNumb == 0){
    console.log("Case 0: Entry value: " + testNumb);
    testNumb = 1;
    console.log("Case 0: Exit value: " + testNumb);
  }else if(testNumb == 1){
    console.log("Case 1: Entry value: " + testNumb);
    testNumb = 2;
    console.log("Case 1: Exit value: " + testNumb);
  }else if(testNumb == 2){
    console.log("Case 2: Entry value: " + testNumb);
    testNumb = 3;
    console.log("Case 2: Exit value: " + testNumb);
  }else if(testNumb == 3){
    console.log("Case 3: Entry value: " + testNumb);
    testNumb = 4;
    console.log("Case 3: Exit value: " + testNumb);
  }else{
    console.log("We made it!");
    console.log("Current Value: " + testNumb);
  };
console.log("Final value: " + testNumb);

Results in Console:

Initial value: 0
Case 0: Entry value: 0
Case 0: Exit value: 1
Final value: 1

Tried: Thinking the problem might be related to an infinite loop scenario I encapsulated the entire if/else in a

var testLoopGuard = 0;
if(testLoopGuard == 0){
  if(testNumb == 4){ testLoopGuard = 1; };
  console.log(testLoopGuard);
};

Which makes no difference, but testLoopGuard stays at 0. Results in Console:

Initial value: 0
Case 0: Entry value: 0
Case 0: Exit value: 1
0
Final value: 1

Tried: My next thought was that perhaps the initial set var testNumb = 0 was being looped instead of just initialized. So I changed it to var testNumb; to call the initialization which sets it to null and initialized it in Case 0 by changing the logic to look for an undefined value. The results stayed the same.

Tried: Next I considered that perhaps it wasn't looping as the main Loop would normally do, so it was only running the first condition and then the program essentially ended. This didn't seem the likely case though, since it was able to listen for user input seemingly infinity when using something such as:

client.on('message', msg => {
  if (msg.content === 'ping') {
    msg.reply('pong');
  }
});

Tried: Out of my own curiosity I tried encapsulating the entire block with a client.on('message'... setup, adding the login as bot code to use it. This semi-worked, but would only go up one step per user entry, but having to enter text to allow it to go up a step or register a change is far from ideal in any program.

client.on('ready', () => {
    console.log(`Logged in as ${client.user.tag}!`);
});

client.login(process.env.DISCORD_TOKEN);

client.once('ready', () => {
    console.log('Ready!');
});


client.on('message', message => {
*original code*
});

Tried: After that I tried moving the console.log("Initial value: " + testNumb); and the console.log("Final value: " + testNumb); outside of the encapsulation, but they only worked once on the first run and never again. Results in Console:

Initial value: 0
Final value: 0
Case 0: Entry Value: 0
Case 0: Exit Value: 1
*user entry*
Case 1: Entry Value: 1
Case 1: Exit Value 2
*user entry*
Case 2: Entry Value: 2
Case 2: Exit Value 3

and so on.

Thoughts: With all this in mind, there is clearly a loop going on to check contents but it for some reason isn't actually doing anything with the contents after the first run through the loop. I am likely missing something simple and I can't find any information on loops other than while and for loops, so I can only assume the main loop is built in by default since it does have the ability to listen and repeat, but if so why is this simple sequence not working? I know it isn't the most fancy way to do things and there are likely much better ways to actually make a full program/bot, but understanding why this doesn't work and how to fix it is pretty key. Thank you for your time and help in advance!

3
Maybe I'm missing something but...what are you actually trying to do? You explain there is a problem but I can't see what solution are you looking for. What's the end goal here? - VLAZ
I hope this is where I respond to you. For now I would just like to know why a simple Switch/Else-if statement isn't running past the first step and is stuck only at case 0 never to run again. If I can understand why this isn't working and how to fix it, then I can move forward. Not sure if that's a great explanation though ^^; - Temporary1
Would this help? When you have an if/else/if/else chain you only get one of the branches. If you want more than one to execute at once, then you need to remove the else so you'd have if (cond1) { /* something */ } if (cond2) { /* something */ } then inside the first if you can change things so cond2 matches. - VLAZ
I'm afraid not, I'm not really trying to to get them to run all at once. I just simplified the logic to where every pass through a different If statement would be true and the others would be false, until the else is the only remaining one. An example would be if I wanted Case 0 to be the "start" of the program where I place all the code and run some simple checks to make sure its making the right connections, then I increment the value so it matches Case 1 which runs a card game, for example, and Case 2 could be a debug mode, where each case would contain a certain role. Just an example - Temporary1

3 Answers

0
votes

Look like the if/else statement is running as expected.

I mean, you init a variable testNumb to 0 and test it, it end up in the first case, that's pretty normal here because the first case compare the variable to 0. How can this be different?

I bet if you init the testNumb variable to 1, it will end up in the second case.

0
votes

Oh, I see what you did.. look:

console.log("Initial value" + testNumb);
if(testNumb == 0){
  console.log("Case 0: Entry value: " + testNumb);
  testNumb = 1;
  console.log("Case 0: Exit value: " + testNumb);
}

There are two problems. The first is with testNumb = 1; You can not change a value outside of the if-statements scope. What happens is testNumb will be redefined to 1 until you close the body with an }

The second problem would be that an if - else statement stops reading the rest of your code if something evaluates to true.

Now how can you make testNumb increment in your case? With a for loop. It would look something like this:

// in this example I use "i" instead of "testNumb"
for (let i = 0; i < 5; i++) {
  console.log("Case " + i + ": Entry value: " + i);
  console.log("Case " + i + ": Exit value: " + i++);
};
console.log("We made it!");
0
votes

I found the solution to the problem after a lot of trial and error.

Within Javascript and Node.js/Discord.js everything is complied and ran once and will only be referenced if another action is called upon, such as a message. The code does end up working as it should if it is called by something like a timer set to run over the code again. It does store the value, but will never touch it again unless an eventlistener calls upon it to work again. Loops wont work, as far as I can find, and will stall since it never finishes compiling. There is no way to use a "main loop" setup. So the only way to do that is to create a psudo loop with a reoccurring eventlistener like timeout.

I'm not sure if the explanation is the greatest or I missed anything, but if there are any better explanations I am more than happy to look them over, until then I'll mark this question as answered. Thanks for the input everyone!