Javascript, What is an uncaught (in promise) DOMException? - javascript

I am getting a (what seems to be) random promise error during my switch statement below. I have created a random number, and associated it with a given array items position. I use this position inside my switch statement to play a specific sound. When testing this inside the browser I sometimes get an in promise exception like below:
playSound # game.js:29
nextSequence # game.js:18
(anonymous) # game.js:45
Even though I get this error everything works as intended. EDIT PIECE: When debugging with debugger; the above is present intermittently
//store colors
var buttonColors = [
"green", //0
"red", //1
"yellow", //2
"blue" //3
]
gamePattern = [ /*Added From nextSequence*/ ]
//Generate a random number
function nextSequence() {
randomNumber = Math.floor(Math.random() * 4)
randomChosenColor = buttonColors[randomNumber];
gamePattern.push(randomChosenColor);
$(`#` + randomChosenColor).fadeOut(100).fadeIn(100).delay(200);
playSound(randomChosenColor);
}
function playSound(color) {
switch (color) {
case 'green':
var greenButton = new Audio('sounds/green.mp3');
greenButton.play();
break;
case 'red':
var redButton = new Audio(`sounds/red.mp3`);
redButton.play();
break;
case `yellow`:
var yellowButton = new Audio(`sounds/yellow.mp3`);
yellowButton.play();
break;
case `blue`:
var blueButton = new Audio(`sounds/blue.mp3`);
blueButton.play();
break;
default:
console.log(`Play Sound Error in playSound Function`)
}
}
nextSequence();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Related

How do you initialize variables inside function scope and avoid global scope?

I have in the global space a variable set as follows:
let hoverMessageLock = 0;
This allows the function below to operate how I want. Its function is to add a message upon button hover and then delete said message and replace it with a new message upon another hover.
The issue I'm having is I would like to NOT use the global space for variables and instead put it inside the function itself. However the function itself is getting called over and over again per each hover event, so if I set hoverMessageLock = 0 in the function scope, it just keeps getting set to 0 over and over again. Therefor my switch statement doesn't work as intended as when its in the global scope.
I know in other programming languages that utilizes classes, you can set variables in the class scope and then alter them in the same way you would global scope inside your functions. Is there a way to do this as well here in Javascript?
let macroManager = {
hoverMessage: function(message, style = "hovertext noTextSelect"){
switch (hoverMessageLock){
case 0:
uiManager.messageDirector.addMessage(""+message+"", 0, 0, style);
hoverMessageLock = 1;
break;
case 1:
uiManager.messageDirector.removeMessage();
uiManager.messageDirector.addMessage(""+message+"", 0, 0, style);
break;
}
},
}
You already have an object, and that works nicely, just as you describe in class-based languages. Classes are simply a way of creating objects, and objects are all you need here.
Just add the property to your object:
let macroManager = {
hoverMessageLock: 0,
hoverMessage: function(message, style = "hovertext noTextSelect"){
switch (this.hoverMessageLock){
case 0:
uiManager.messageDirector.addMessage(""+message+"", 0, 0, style);
this.hoverMessageLock = 1;
break;
case 1:
uiManager.messageDirector.removeMessage();
uiManager.messageDirector.addMessage(""+message+"", 0, 0, style);
break;
}
},
}
Note that, depending on how you use the hoverMessageLock method, it's possible its this context could be lost (eg if you use it as an event handler) - this is easily fixed by defining it as an arrow function instead: hoverMessage: (message, style = "hovertext noTextSelect") => { ... }.
I would also recommend, if 0 and 1 are the only intended values of the hoverMessageLock variable/property, using boolean false/true values instead.
You can use an Immediately Executed Function Expression (IIFE) for this.
let macroManager = (function(hoverMessageLock) {
return {
hoverMessage: function(message, style = "hovertext noTextSelect") {
switch (hoverMessageLock) {
case 0:
uiManager.messageDirector.addMessage("" + message + "", 0, 0, style);
hoverMessageLock = 1;
break;
case 1:
uiManager.messageDirector.removeMessage();
uiManager.messageDirector.addMessage("" + message + "", 0, 0, style);
break;
}
},
};
})(0);
class macroManger{
constructor(){
this.hoverMessageLock = 0;
}
hoverMessage(message, style = "hovertext noTextSelect"){
switch (this.hoverMessageLock) {
case 0:
uiManager.messageDirector.addMessage("" + message + "", 0, 0, style);
this.hoverMessageLock = 1;
break;
case 1:
uiManager.messageDirector.removeMessage();
uiManager.messageDirector.addMessage("" + message + "", 0, 0, style);
break;
}
}
}
macroManger1 = new macroManger();
macroManger1.hoverMessage(...);
You could create a local scope using the IIFE expression:
var macroManager = getMacroManager();
function getMacroManager() {
return (function () {
var hoverMessageLock = 0;
return {
hoverMessage: function (message, style = "hovertext noTextSelect") {
switch (hoverMessageLock) {
case 0:
uiManager.messageDirector.addMessage("" + message + "", 0, 0, style);
hoverMessageLock = 1;
break;
case 1:
uiManager.messageDirector.removeMessage();
uiManager.messageDirector.addMessage("" + message + "", 0, 0, style);
break;
}
},
};
})();
}
So each time you call getMacroManager() you will get a separate instance, thus, hoverMessageLock will work as a local variable, which is what you expect to happen.
Here's more info about IIFE:
https://developer.mozilla.org/en-US/docs/Glossary/IIFE.

Javascript scope variable to switch case?

In C you can scope a variable to a switch case, like this.
With javascript I get unexpected token using the following:
const i = 1
switch (i) {
// variables scoped to switch
var s
var x = 2342
case 0:
s = 1 + x
break
case 1:
s = 'b'
break
}
Is there another way to do this or should I just declare my variables outside the switch?
EDIT:
This is a workaround I considered but it didn't end up working. The reason being that each case has its own scope.
const i = 1
switch (i) {
case i:
// variables scoped to switch
var s
var x = 2342
case 0:
s = 1 + x
break
case 1:
s = 'b'
break
}
some alternative:
/* curly braces inside the case */
const i = 1
switch (i) {
case 0: {
let x = 2342;
let s = 1 + x;
console.log(x+' & '+s+' from inside');
} break;
case 1: {
let x = 2342;
let s = 'b';
console.log(x+' & '+s+' from inside'); /* 2342 & b from inside */
} break;
}
console.log(x+' & '+s+' from outside'); /* Uncaught ReferenceError */
or
/* curly braces outside the switch */
const i = 1
{
let x = 2342;
let s;
switch (i) {
case 0:
s = 1 + x;
break;
case 1:
s = 'b';
break;
}
console.log(x+' & '+s+' from inside'); /* 2342 & b from inside */
}
console.log(x+' & '+s+' from outside'); /* Uncaught ReferenceError */
Since var creates variables at function scope anyway, using it is pretty pointless. For this to work at a granularity below function scopes you'll have to use let and a browser/compiler which supports it, and then introduce a new block which you can scope things to (within switch it's simply invalid syntax):
if (true) {
let s;
switch (i) {
...
}
}
This scopes s to the if block, which for all intents and purposes is identical to the "switch scope" here.
If you cannot support let, you'll need to use an IIFE:
(function () {
var s;
switch (...) ...
})();
No, this is invalid syntax. A case or default statement is expected within a switch. You can check the specification here: http://www.ecma-international.org/ecma-262/5.1/#sec-12.11
You can also try entering your code in a JSLinter and see that this an error: http://jslint.com/
Expected 'case' and instead saw 'var'.
The workaround that you're considering would be the same thing as putting them outside the switch statement. Remember, var has function-level scope, not block-level scope. That means they are bound to the entire function containing the switch. You should declare them outside of the switch because that is where they are accessible.
const i = 1;
var s;
var x = 2342;
switch (i) {
case 0:
s = 1 + x;
break;
case 1:
s = 'b';
break;
default:
break;
}
console.log("s is " + s);
It should be declared outside the switch. The below might help:
var i = 1, x = 2342;
var s;
switch (i)
{
case 0:
s = 1 + x;
break;
case 1:
s = 'b';
break;
}
console.log("s is " + s);
JavaScript defines 3 levels of scope:
Global - Anything not delcared in a function
Function - Anything declared in a function using the var keyword
Block - Anything declared in a block container ({}) using let
So, to creae a scope an entire construct, you have two choices: Function or Block
In order to get the the behavior you are looking for with a function:
const i = 1
function doSwitch(data){
// variables are not scoped to switch, but are
// scoped to the function, which only contains
// the switch.
var s;
var x = 2342;
switch (data) {
case 0:
s = 1 + x;
break;
case 1:
s = 'b';
break;
default:
s = "other";
}
console.log("s is " + s)
}
doSwitch(18);
Or, in order to get the functionality with a block using let
const i = 1;
// Wrapping the switch in its own block allows for let to work:
{
// variables are not scoped to switch, but are
// scoped to the function, which only contains
// the switch.
let s;
let x = 2342;
switch (i) {
case 0:
s = 1 + x;
break;
case 1:
s = 'b';
break;
default:
s = "other";
}
console.log("s is " + s)
}
// Test:
console.log(s, x); // ReferenceError

Having Trouble Understanding Javascript Methods

This is my current assignment :
Add a method that will increase the value of one of the numeric properties.
Add a method that will decrease the value of the same numeric property.
Create a for loop after creating an instance of the character. The loop will iterate 100 times.
Inside the loop call one of the methods based on a random number from zero to 3. Using a switch statement, if the value is 0 then call the method that losses; 1 don’t call anything; 2 call the method that gains.
Here is my current coding. I know I'm doing something wrong. I just can't figure out what I am doing wrong with the switch statement.
var BR = "<br />";
function person(name, sandwiches) {
this.name = name;
this.sandwiches = sandwiches;
function jump() {
var text = " leaps over an obstacle.";
return fname + text;
}
function run() {
var text = " runs as fast as they can";
return fname + text;
}
function dodge() {
var attack = math.random();
var att = math.round(attack);
var defense = math.random();
var def = math.round(defense);
if(att > def) {
return "You missed";
}
else {
return "You dodged";
}
}
function date() {
var today = new Date();
return today.toDateString();
}
function shout() {
var word = "Oh no";
return word.toUpperCase();
}
this.addSandwich = function (sandwiches) {
sandwiches = sandwiches + 1;
return sandwiches;
};
this.loseSandwich = function (sandwiches) {
sandwiches = sandwiches - 1;
return sandwiches;
};
}
var character = new person("Jerry", 1);
for(i=0; i < 100; i++) {
var random = Math.floor(Math.random() * 3);
switch(random) {
case 0:
character.loseSandwich(character.sandwiches);
console.log(sandwiches);
break;
case 1:
break;
case 2:
character.addSandwich(character.sandwiches);
break;
}
}
document.write("Name: " + character.name + BR);
document.write("Sandwiches: " + character.sandwiches + BR);
Math.floor(Math.random() * 3) is not what you want.
You want something like Math.random() % 3 to get 0, 1, or 2 every single time
Not sure if this is your problem, but it is at least one of them;
In a few places you have a lowercase math, for example:
function dodge() {
var attack = math.random();
JavaScript is case-sensitive, and it should be Math.random() not math.random()
Another issue is that these functions:
this.addSandwich = function (sandwiches) {
sandwiches = sandwiches + 1;
return sandwiches;
};
do not change the number of sandwiches. You get in a value of sandwiches, add or subtract 1, then return that changed number, but never use the returned result.
You are only changing the value of the variable that was passed in, not changing the number of sandwiches on the instance of the person.
Note that this.sandwiches (the variable on the instance of a person) is not the same variable as sandwiches (the function argument)
I dont think there is any reason to pass the number of sandwiches into those functions, and they could just do:
this.addSandwich = function () {
this.sandwiches = this.sandwiches + 1;
};
or more simply:
this.addSandwich = function () {
this.sandwiches++;
};
Another problem here:
character.loseSandwich(character.sandwiches);
console.log(sandwiches);
The console.log statement is trying to log sandwiches but that is not a variable at that point. You probably wanted console.log(character.sandwiches); However this wouldn't cause an exception, it would just always log undefined.

JavaScript - For loop with switch statement continually looping

I'm relatively new to coding and working on a text based RPG game in JavaScript. The following code allows me to progress through the different scenarios where you are approached with a different bad guy.
I used a For loop in conjunction with a Switch statement and had it working prior, but then I re factored my code to make it more OO & prototypal. Now my For loop continues looping and does not exit. I checked the value of [i] throughout and see it properly goes 0-4, but then it restarts at 0 and I can't figure out why?
var scenario = new Array();
//simple function to create the number of scenarios
function Scenario () {
howManyScenarios = function(number) {
for (i=0; i <= number; i++) {
scenario[i] = ("Scenario " + (1 + i));
};
};
howManyScenarios(4); //if you change the argument, add additional switch cases
//iterating through my howManyScenarios function to build out scenarios using a switch case
createScenarios = function () {
var ii = scenario.length;
for (i=0; i < ii; i++) {
switch(scenario[i]) {
case 'Scenario 1':
alert("You run into a troll");
b = 0;
break;
case 'Scenario 2':
alert("You find a store to purchase goods from");
ItemShop();
break;
case 'Scenario 3':
alert("You run into a ogre");
b = 1;
break;
case 'Scenario 4':
alert("You run into a warewolf");
b = 2;
break;
case 'Scenario 5':
alert("You run into a wizard");
b = 3;
return;
break;
}; //close out switch cases
}; //close out my for loop
}; //close out createScenarios function
createScenarios();
}; //close out Scenario function
Scenario();
Your loop will obviously still continue because you just only ended a case of every loop of i and will still test each value in the array of scenario[i].
How about using variable b as a handler that if an event like you run into a troll has been executed, then set b to a number greater than 0 then check if a value has been inserted into b before switching into the array again using if (b) break; where if b has a value greater than 0 then it will be set as true.
var scenario = new Array();
var b;
//simple function to create the number of scenarios
function Scenario() {
howManyScenarios = function (number) {
for (i = 0; i <= number; i++) {
scenario[i] = ("Scenario " + (1 + i));
};
};
howManyScenarios(4); //if you change the argument, add additional switch cases
console.log(scenario[i]);
//iterating through my howManyScenarios function to build out scenarios using a switch case
createScenarios = function () {
var ii = scenario.length;
for (i = 0; i < ii; i++) {
if (b) break;
switch (scenario[i]) {
case 'Scenario 1':
alert("You run into a troll");
b = 1;
break;
case 'Scenario 2':
alert("You find a store to purchase goods from");
b = 2;
ItemShop();
break;
case 'Scenario 3':
alert("You run into a ogre");
b = 3;
break;
case 'Scenario 4':
alert("You run into a warewolf");
b = 4;
break;
case 'Scenario 5':
alert("You run into a wizard");
b = 5;
return;
break;
}; //close out switch cases
}; //close out my for loop
}; //close out createScenarios function
createScenarios();
}; //close out Scenario function
Scenario();
function ItemShop() {}
ANSWER 2
This one is one way on how we game developers make a functional game by using a series of object arrays, object classes and the like.
I remade your code into something easier to read, hope you learn something from this. :)
var numberofscenarios = 5;
var scenario = []; //array where scenarios will be
//this will be the accessible properties of scenario[] array
var _scenario = function(){
this.name = ""; //name of scenario
this.message = "";
this.doSomething = 0;
this.status = 0 ;//1 = finished and 0 = false
};
var _event = function(mobname){
this.mobname = mobname;
this.battle = function(){//doSomething
console.log("Battle VS "+ this.mobname +" Start!");
};
this.itemShop = function(){//doSomething
console.log(this.mobname + ": Welcome to the shop! How may I help you?");
};
};
//generate the scenarios in the scenario[] array
function generateScenarios() {
for (i = 0; i <= numberofscenarios; i++) {
scenario[i] = new _scenario();
scenario[i].name = i;
switch (scenario[i].name) {
case 1:
scenario[i].message = "You run into a Troll";
scenario[i].doSomething = new _event("Troll");
break;
case 2:
scenario[i].message = "You find a store to purchase goods from";
scenario[i].doSomething = new _event("Shop Keeper");
break;
case 3:
scenario[i].message = "You run into a Ogre";
scenario[i].doSomething = new _event("Ogre");
break;
case 4:
scenario[i].message = "You run into a Werewolf";
scenario[i].doSomething = new _event("Werewolf");
break;
case 5:
scenario[i].message = "You run into a Wizard";
scenario[i].doSomething = new _event("Wizard");
break;
}
}
}
generateScenarios(); //generate the scenarios
//test the array of scenario class
//test the battle with Troll
console.log(scenario[1].message);
scenario[1].doSomething.battle();
//test the shop
console.log(scenario[2].message);
scenario[2].doSomething.itemShop();
//attempt to fight the Shopkeeper
console.log(scenario[2].message);
scenario[2].doSomething.battle();

How do I use one function to call the other function by if/case statement?

Does anyone know what typo I made, because my editor, and I can't seem to make it work
number=5;
switch (number) {
case 5:
box.onclick = function1;
break;
case 50:
box.onclick = function2;
break;
}
I've also tried doing it in switch.
Try not using the reserved word var as a variable name:
var x=5;
if (x==5){
box.onclick = function1;
}
if(x==50){
box.onclick = function2;
}
var is the reserved word to create variables. You can't use it as a name. This is the correct syntax:
var x = 5;
if (x == 5) {
box.onclick = function1;
}
if (x == 50) {
box.onclick = function2;
}
With this code:
number=5;
switch (number) {
case 5:
box.onclick = function1;
break;
case 50:
box.onclick = function2;
break;
}
case 50 will never be hit because you set number to 5 before entering the switch block. Therefore box onclick will never equal function2. Therefore, when you click the box, function2 will not be run. Is this really an accurate representation of your actual code, or is it a simplification that has left out important information?
You can't use reserved JavaScript words for declaring variables.
Try to replace var=5 to myVar=5 for example.
var myVar = 5;
if (myVar ==5){
box.onclick = function1;
}
if(myVar ==50){
box.onclick = function2;
}
Also, check out this reference: JavaScript Reserved Words

Categories