0

when I generate random numbers with JavaScript language (using Node JS) when I refresh the page, the random numbers don't change, the only way to change them is for me to restart the server. Here is the code snippet.

'''
const random = Math.round(Math.random() * 1);

const firstNumber = random ? (Math.random() * (10000) - 5000).toFixed(2) :
  (Math.round(Math.random() * (100)) - 50);
const secondNumber = random ? (Math.random() * (10000) - 5000).toFixed(2) :
  (Math.round(Math.random() * (100)) - 50);
const operations = random ? ["+", "-"] : ["*", "/"];

const randomOperation = operations[Math.round(Math.random() * 1)];
const expression = firstNumber + randomOperation + secondNumber;
const resultNotInterger = eval(expression);
const result = Number(resultNotInterger).toFixed(2);

///////////

app.get("/", function(request, response) {
  response.render("index.ejs", {
    firstNumber: firstNumber,
    secondNumber: secondNumber,
    randomOperation: randomOperation,
    result: result
  });
});

app.post("/", function(request, response) {
  const clientResponse = Number(request.body.clientResponse).toFixed(2);
  if (clientResponse === result) {
    console.log("Good");
  } else {
    console.log("Bad");
  }
  response.redirect("/");
});
'''
  • 1
    It depends on where/when you generate the random number in your server code. So seeing that would be useful. – Nick Parsons Jul 22 '20 at 02:41
  • Does this relate to your previous question? – Pavlos Karalis Jul 22 '20 at 02:44
  • @PavlosKaralis Yes it does –  Jul 22 '20 at 02:45
  • 1
    @NickParsons I will post it in a few seconds –  Jul 22 '20 at 02:46
  • 2
    @WiseEye When you start your server, the entire file runs, creating the random number and registering the `.get()` routes etc. The code which runs when you visit your site is in the `.get('/', function() {//here})` callback, the code outside of that doesn't run. You'll want to generate the random number in the callback – Nick Parsons Jul 22 '20 at 02:49
  • 1
    Move the variables inside your .get route and it should work – Pavlos Karalis Jul 22 '20 at 02:51
  • Thank you both, it worked! If any of you would like to put that as the answer for the question would be good, I can approve it. That way when other people have the same question it will be ease to see the answer. –  Jul 22 '20 at 02:57

1 Answers1

1

You're currently only generating your random numbers when the server initially starts up, which happens once, not every time the page loads. When your server initially starts, it registers routes for GET and POST requests. When you search for a URL in your search bar, you're performing a HTTP GET request to a specific path. In your case, if that path matches / the callback for your .get('/', <callback>) will be invoked.

This means that if you want a particular action to occur when you visit your site, you'll need to put your logic in this callback (or add it as middleware). Currently, you're rendering your page and sending that back to the client's browser to be viewed as HTML. However, you can do more than just this, such as generate your random numbers:

app.get("/", function(request, response) { // Invoked when get request is sent to the path `/`
   /*
     Add random number logic here which calculates:
     `firstNumber`, `secondNumber`, `randomOperation` and `result`.
   */
  response.render("index.ejs", {
    firstNumber: firstNumber,
    secondNumber: secondNumber,
    randomOperation: randomOperation,
    result: result
  });
});

Side notes:

Your code could also do with a little refactoring. Currently your firstNumber and secondNumber repeat the same code, this could be decomposed into a function:

function getRandNumber(random) {
  return random ? (Math.random() * (10000) - 5000).toFixed(2) : (Math.round(Math.random() * (100)) - 50);
}

Or, if you prefer, you can use an arrow function instead:

const getRandomNumber = random => random ? (Math.random() * (10000) - 5000).toFixed(2) : (Math.round(Math.random() * (100)) - 50);

Using eval() is often frowned upon, and there is usually a way to avoid using it. Since you have a fixed number of operations, you can define an object which keeps keys as the operation strings, and values as functions which perform that operation between two input numbers:

const operationsMap = {
  '+': (x, y) => x + y,
  '-': (x, y) => x - y,
  '/': (x, y) => x / y,
  '*': (x, y) => x * y
};

Now if you do operationsMap['+'], you will get the function (x, y) => x + y, which you can then call to get the answer for adding two numbers x and y.

So, refactoring your code a little, you can make it look like;

// Objects and functions which live outside of your `.get()`
const operationsMap = {
  '+': (x, y) => x + y,
  '-': (x, y) => x - y,
  '/': (x, y) => x / y,
  '*': (x, y) => x * y
};
const getRandomNumber = random => random ? (Math.random() * (10000) - 5000).toFixed(2) : (Math.round(Math.random() * (100)) - 50);

// Code for computing random numbers (could be in its own function and called inside the `.get()` callback function)
const random = Math.round(Math.random() * 1);
const firstNumber = getRandomNumber(random);
const secondNumber = getRandomNumber(random);
const operations = random ? ["+", "-"] : ["*", "/"];

const randomOperation = operations[Math.round(Math.random() * 1)];
const resultNumber = operationsMap[randomOperation](firstNumber, secondNumber);
const result = resultNumber.toFixed(2);
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64