Why does this code create an infinite loop? - javascript

I have a JavaScript problem. I have a function that runs when I hit a button, the variables are changed via JavaScript. Everything in the function runs properly but this one last part:
else if (upgrade == "upgMiner4") {
var cost="500";
var qty="1";
var readCash=parseInt(document.getElementById("cash").innerHTML);
while (readCash >= cost) {
document.getElementById("cash").innerHTML += "-"+cost;
document.getElementById("cash").innerHTML = eval(document.getElementById("cash").innerHTML);
document.getElementById("gpt").innerHTML += "+"+qty;
document.getElementById("gpt").innerHTML = eval(document.getElementById("gpt").innerHTML);
}
}
When I run this code, it freezes and creates an infinite loop. I don't see the problem here, so I would like to know if you guys could help me, thanks!
-Zachucks

Your code inside the while loop does nothing to update readCash or cost, so if the condition (readCash >= cost) is true, this will never change, and the while loop will never exit.
I should add that a reader cannot tell what the evals are evaluating--so it's hard to be sure what is going on. However, notice you assign to readCash and cost exactly one time and that you never do this again. So why would it change?

Because you set readCash value only once and don't update it together with innerHTML with your div. That's why your loop doesn't end.
Working code:
while (readCash >= cost) {
document.getElementById("cash").innerHTML += "-"+cost;
document.getElementById("cash").innerHTML = eval(document.getElementById("cash").innerHTML);
document.getElementById("gpt").innerHTML += "+"+qty;
document.getElementById("gpt").innerHTML = eval(document.getElementById("gpt").innerHTML);
readCash = document.getElementById("cash").innerHTML;
}

neither readCash or cost variable are changing in the last while loop. That's why you're facing a loop. Probably you have to increment/decrement readCash or cost vars with a logic you're missing. Or maybe you don't actually need a while statement, but simply an if

Related

the counter of for of loop in javascript

I am studying javascript, and learning for loop. I am sure it's basic part but I can't get how the counter variable works..
I am making the battle application, and this is the function that is executed when user clicks the battle log, then it will show the last log and the index of it in console.log.
The battle log in the function is the array that stores nested arrays of users input.
let lastLoggedEntry;
function printLogHandler() {
let i = 0;
for (const logEntry of battleLog) {
if ((!lastLoggedEntry && lastLoggedEntry !== 0) || lastLoggedEntry < i) {
console.log(`#${i}`);
for (const key in logEntry) {
console.log(`${key} => ${logEntry[key]}`);
}
lastLoggedEntry = i;
break;
}
i++;
}
}
My question is the initial valuable is set in outside of the for loop(i = 0). but when the user clicks the battle log again, and this function executes again, how for loops has been saving the data of last i and logEntry's value? ( second time when user clisks, it will be i = 1, and logEntry = 0 already)
Also, how can it skip "let i = 0" from second time? because its not only for loop, it executes the function, I thought javascript reads let i = 0 again and it will reset to 0. ( it won't of course but I want to understand why)
Hopefully, you guys could help me out. Thank you,
A few things:
There is missing closure in the sample provided. There should be another closing bracket for the code to validate.
lastLoggedEntry must be defined as a variable before it is used.
It is not clear what the contents of battleLog are.
I think if you clarify these things it may be easier to answer your question.

Apps Script extremely slow or endlessly "Preparing for execution..."

I have written a very simple code on my Google Sheets file. This is the purpose:
Save some cells values from StaticSheet (all the Copyxxx) that need to be copied in DynamicSheet.
Get the value of one specific cell inserted by the user manually.
Enter a While loop useful only to increase an indicator and get the number of the row where I want to copy those values previously saved.
Copy those values on this row but different columns.
The problem is that it seems that most of the time it does not even run the script after I told it to do so.
What is funny is that sometimes it works, super slowly, but it works for like a couple of minutes. And after it stops working again.
Could you please tell me what am I missing here please?
function Copy_Static_on_Dynamic() {
var app = SpreadsheetApp;
var ss = app.openById("xxxxyy--------yyzzzz")
var StaticSheet = ss.getSheetByName("DEAT Price");
var DynamicSheet = ss.getSheetByName("DEAT Price + TEST");
var CopySKU = StaticSheet.getRange(5,1,40);
var CopyPrices = StaticSheet.getRange(5,3,40,4);
var CopyUsage = StaticSheet.getRange(5,8,40);
var Week_1 = StaticSheet.getRange(2,4).getValues();
var i = 1;
Logger.clear();
while(DynamicSheet.getRange(i,3).getValues() != Week_1)
{
Logger.log(i);
i+=1;
}
CopySKU.copyTo(DynamicSheet.getRange(i,4,40));
CopyPrices.copyTo(DynamicSheet.getRange(i,6,40,4));
CopyUsage.copyTo(DynamicSheet.getRange(i,11,40));
}
If you see the "Preparing for Execution" message in the Apps Script editor, you can reload the browser window and run the function again. The program will likely go away.
So I think I have solved it.
As Serge insas was saying I had my script running on the background, I found it out on the "Execution" section, where you can also interrupt them.
After I discover it I kept testing, and I saw that the while loop needed almost 2 seconds to check the condition every time, making the script incredibly long.
So instead of:
while(DynamicSheet.getRange(i,3).getValues() != Week_1)
... I have created a variable declared previously such as:
var WeekLOOP = DynamicSheet.getRange(i,3).getValues();
while(WeekLOOP != Week_1) { --- }
... and now the script needs few milliseconds to run the condition. I don't have enough technical knowledge to say if this was the only issue, but is what apparently solved my problem.
Thanks to all for the support! Will come back if I need any further help :)
As was mentioned by Amit Agarwal, to solve the error message mentioned on the question, refresh the web browser tab.
Regarding the code,
On
var Week_1 = StaticSheet.getRange(2,4).getValues();
and
DynamicSheet.getRange(i,3).getValues()
instead of getValues you should use getValue because your code are referring to single cell cells otherwise you will be getting 2D arrays instead of scalar values.
The use of while should be made very carefully to avoid functions running endlessly. You could add some "safeguard" like the following
var max_iterations = 100 // Edit this
while(DynamicSheet.getRange(i,3).getValue() != Week_1 && i <= max_iterations) {

javascript - if statement excecutes both if and else blocks

This is my code:
var counter = 0;
function showAddButton() {
var cnt = document.getElementsByClassName('img-cntnr').length;
counter++; // for detecting double excecution in debugger
if (cnt < 4) {
$('#div-add').show();
} else {
$('#div-add').hide();
}
}
//someweher in my code
showAddButton();
when I call function in my code, JavaScript executes both $('#div-add').show(); and $('#div-add').hide(); lines.
I've defined a variable (counter) and watched that in debugger for detecting parallel twice call. but there is not any parallel execution and in first call if-statement executes both blocks!
how can I fix that?
Thank You.
Your issue is most likely your if statement is not the logic you want perhaps your < should be a >, because even if you were hitting it multiple times that shouldn't really effect the results of the problem because the only way for the else to hit would be if you count was actually greater than what you expected.
So either something else is hiding the div, something is modifying the class count, or your logic is not what you expected it to be.
However you can try this line of code which will get rid of all the excess logic you have
$('#div-add').toggle($('.img-cntnr').length < 4)
you can use a boolean in the toggle fuction to set the display
you can see the toggle documentation here
Here look at this jsFiddle
I cannot see any duplicate calls, nor that both blocks of if/else are executed in one call.
showAddButton always shows element because it depends on:
document.getElementsByClassName('img-cntnr').length;
which gets length of how many elements matched img-cntnr class. So, unless you are adding elements with that class to the DOM, that count will always be the same.
If you can show us jsFiddle that prints both show and hide we will have something to go by.
There is definitely something else that is causing the code to run again. What I would do is add a killer to your js and modify the else statement to look like this:
var counter = 0;
var killer = false;
function showAddButton() {
var cnt = document.getElementsByClassName('img-cntnr').length;
counter++; // for detecting double excecution in debugger
if (cnt < 4) {
$('#div-add').show();
killer = true
} else if(killer === false) {
$('#div-add').hide();
}
}
//someweher in my code
showAddButton();

Can't run two for loop statement within same if statement?

I have the following JS code, I feel weird that only the first for loop can run, but the 2nd part doesn't work. I even tried to make two different if statement and include the for loop separately, but the same thing happened. If I run the for loop separately (by deleting another for loop), both of them can run, means both of the logic should be correct. Please help.
var s = "<?php printf($resultDataOrderInfo[0][status]); ?>";
if(s == "Processing"){
var t = document.getElementsByTagName("input");
for (i=0; i<=t.length; i++){
t[i].setAttribute("readonly","true");
} // only this above part can run
var d = document.getElementsByName("delete");
for (i=0; i<=d.length; i++){
d[i].setAttribute("hidden","true");
}
}
I think you want to change all of the <= to <. If length is equal to 0, then it is going to execute once, but fail due to the length being zero. Which, I believe is the issue of it not reaching the second for loop, due to an error occurring on the first.

Writing Multiple into the same ID on HTML

Someone know if after I displays an HTML page I can access a specific ID (getElementById), and change it a value several times?
I want to present a client-side some string and change it several times according the progress of the program, but I can not, it writes to me only recently.
For example:
<script type="text/javascript">
function foo(){
for(var i = 0; i<10000; i++){
document.getElementById('myTag').innerHTML = i;
}
}
</script>
In this case, I do not see the numbers run. I see only the last one.
If I put alert inside the loop - the value is changed.
As i understand your question you want a countup from 0 to 10000 ?
and you want to see the progression on screen ? you could do something like that :
http://jsfiddle.net/camus/ayJFM/
var interval = 500;//milliseconds
var foo = (function () {
var i = 0;
var func = function () {
if (i < 10000) {
document.getElementById("myTag").innerHTML = i;
i += 1;
setTimeout(func, interval);
}
};
return func;
})();
setTimeout(foo, interval);
You're almost there. The only thing you're doing wrong is replacing the innerHTML content instead of adding to it. Change this:
document.getElementById('myTag').innerHTML = i;
to this:
document.getElementById('myTag').innerHTML += i;
Additional/alternative answer:
Wait. I've just reread your question and realized that there is another way of interpreting it. The way you ask it is quite vague so I'm leaving the above answer as is.
The reason you don't see "running numbers" as you process the for loop is because you misunderstand how javascript works in the browser.
The browser's event loop runs something like this:
1. Fetch content
2. Run javscript
3. Render content
then repeat forever
This is how javascript works. So running a simple for loop like you're doing. The browser executes the script until there is nothing else to execute (step 2). Once javascript have finished executing then it will start the render process (step 3). Obviously, by this time the value of i is the final value and therefore you only see the final value.
The browser never interrupts running javascript to render/update the page. So, how do people implement countdown timers etc? They do it by scheduling a piece of javascript to execute in the next iteration of the event loop. That is to say, the let the browser enter step 3 and at the appropriate moment as the browser enters step 2 again they run the script they want.
Javascript basically provides two ways to do this: setTimeout and setInterval.
How setTimeout works is this:
step 1. nothing to do
step 2. setTimeout schedules a piece of javascript to run at a later time
Note that the javascript does not execute yet until setTimeout
expires.
step 3. let the browser update the page
many, many loops of steps 1-3
step 2 (some time later).
setTimeout expires and the piece of javascript executes
step 3. let the browser update the page
So, the get the effect you want, you need to do it like this:
function foo(){
var i = 0;
var update = function(){
document.getElementById('myTag').innerHTML = i;
i++;
if (i<10000) {
setTimeout(update,100);
}
};
update();
}

Categories