I am writing code to learn defensive error handling in javascript. The program calculates distance, time or speed depending on the user's choice. This bit works fine.
I then tried to add a try catch statement under the prompt-time function and this worked. So I took that code and tried making it into one function rather than typing it out thrice. The idea is that if the user enters something that is not a number or blank the program will keep asking for a number until they do.
But now whenever I enter something that is not a number the while loop does not show the prompt and loops indefinitely. I need a while loop as using an if statement makes the program go on without the correct output.
I am not sure why this is happening.
ask = prompt('Calculate distance(d), time (t) or speed (s)')
function notNumber(input) {
while (true)
try {
let input = Number(prompt('Enter your ' input))
if (isNaN(input) == true || input == "") {
throw "Invalid Input";
}
return input;
}
catch (err) {
console.log(err);
}
}
function promptTime(time) {
time = Number(prompt('Enter your Time'))
if (isNaN(time)) {
notNumber(time)
}
return time;
}
function promptSpeed(speed) {
speed = Number(prompt('Enter your Speed'))
if (isNaN(speed)) {
notNumber(speed)
}
return speed;
}
function promptDistance(distance) {
distance = Number(prompt('Enter your distance'))
if (isNaN(distance)) {
notNumber(distance)
}
return distance;
}
if (ask == 'd') {
let time = promptTime()
let speed = promptSpeed()
distance = time * speed
if (distance == Number) {
console.log('Your distance is ' distance)
}
if(isNaN(distance)) {
notNumber(distance)
}
}
else if (ask == 't') {
let distance = promptDistance()
let speed = promptSpeed()
time = distance / speed
console.log('Your time is ' time)
if(isNaN(time)) {
notNumber(time)
}
}
else if (ask == 's') {
let distance = promptDistance()
let time = promptTime()
speed = distance / time
console.log('Your speed is ' speed)
if(isNaN(speed)) {
notNumber(speed)
}
}
else {
console.log('Please enter a measurement!')
}
CodePudding user response:
The issue is that you are using the same variable name input both in the function parameter and within the function body. When you pass in a variable as an argument to the function, that variable is being passed by reference. So when you reassign the value of input inside the function, you are also modifying the value of the variable passed as an argument.
You can fix this by using a different variable name in the function body. Here is an example of how you can modify the function:
function promptNumber(name) {
while (true) {
try {
let input = Number(prompt(`Enter your ${name}`));
if (input == "" && isNaN(input)) {
throw "Invalid Input";
}
return Number(input);
} catch (err) {
console.log(err);
}
}
}
In this example, the function promptNumber takes in a parameter name which is used to display the prompt message and a new variable inputNum is used inside the function to store the user input.
You sign notice, isNaN(input) == true
can be simplified by isNaN(input)
which is already a boolean. It is good to learn this kind of good practices, makes code clearer and simpler.
Here is another way to improve your code :
You can then call this function in place of the promptTime, promptSpeed, promptDistance functions with the appropriate name
argument:
let time = promptNumber("time");
let speed = promptNumber("speed");
let distance = promptNumber("distance");
In this way you avoid the scope issue and you can use the same function for all the prompt calls.
Ask me if you have more questions.
CodePudding user response:
Here's the answer to your new question.
I think there is still a bit of confusion. First, replace variable
by refer
as it is the value you want to display in the text when the user writes its input.
Now that it's done, let's see the function promptTime :
function promptTime(time) {
time = Number(prompt('Enter your Time')) // NO ! you're using promptNumber later to ask the user to enter the number. You don't prompt here !
refer = 'time'
if (isNaN(time)) { // No need to put this inside an if. Just call `promptNumber(refer)`
time = promptNumber(time)
}
return time;
}
And you can think the same way for the others 2 (promtSpeed & promptDistance.
I'm gonna go to bed so I'll answer tomorrow if you have more questions. Feel free to ask :)
CodePudding user response:
Changes: Redefined the promptNumber function from 'input' to a different name ('variable')
Added refer variable to get the name of the desired calculation (time, speed or distance)
Note that I tried calling 'refer' 'name'. But name came up as deprecated.
Got rid of the nested if statements as they are now redundant. For example:
else if (ask == 't') {
let distance = promptDistance()
let speed = promptSpeed()
time = distance / speed
console.log('Your time is ' time)
/* Got rid of statements like these
if(isNaN(time)) {
notNumber(time)
}
*/
}
The finalised code is:
ask = prompt('Calculate distance(d), time (t) or speed (s)')
function promptNumber(variable) {
while (true) {
try {
let input = Number(prompt(`Enter a number for ${refer}`));
if (input == "" || isNaN(input)) {
throw "Invalid Input";
}
return Number(input);
} catch (err) {
console.log(err);
}
}
}
function promptTime(time) {
time = Number(prompt('Enter your Time'))
refer = 'time'
if (isNaN(time)) {
time = promptNumber(time)
}
else {
return time;
}
return time;
}
function promptSpeed(speed) {
speed = Number(prompt('Enter your Speed'))
refer = 'speed'
if (isNaN(speed)) {
speed = promptNumber(speed)
}
else {
return speed;
}
return speed;
}
function promptDistance(distance) {
distance = Number(prompt('Enter your distance'))
refer = 'distance'
if (isNaN(distance)) {
distance = promptNumber(distance)
}
else {
return distance;
}
return distance;
}
let refer = ''
if (ask == 'd') {
let time = promptTime()
let speed = promptSpeed()
distance = time * speed
console.log('Your distance is ' distance)
}
else if (ask == 't') {
let distance = promptDistance()
let speed = promptSpeed()
time = distance / speed
console.log('Your time is ' time)
}
else if (ask == 's') {
let distance = promptDistance()
let time = promptTime()
speed = distance / time
console.log('Your speed is ' speed)
}
else {
console.log('Please enter a measurement!')
}