JS Loop is looping and crashing browser? - javascript

for (i=0;i<channelName.length;i++) {
if (channelName[i]=="channel"||channelName[i]=="user") {
checkUserDuplicate(channelName[i]);
}
}
This loop is causing an "out of memory" crash in all browsers. can anyone see why? It seems to be crashing at the IF statement and then causing an infinite loop somehow.
If you're wondering what the code does, it finds the keywords "channel" and "user" in an array of undefined length, then gets the string at the next position.
Any help would be much appreciated as I have been sitting here puzzled for 2 hours.
EDIT: channelName is a URL like http://www.youtube.com/user/username
this is the function:
function checkUserDuplicate(channelName) {
var idarray=[];match=0;$('.channels').each(function(){idarray.push(this.id)});
for (i=0;i<idarray.length;i++) {
var current=channelName.toLowerCase();compare=idarray[i].toLowerCase();
if (current==compare) {callError(channelName+" already exists in this collection");match=1;}
} if (match==0) {checkExists(channelName);}
}
It's a mess :)

In your for loop, if you don't specify var i = 0;, it's globally accessible then. And in your other functions, you may modify the value of i and cause it doesn't increment as expected ends up with an infinite loop.
Sorry I didn't read the code since it's pretty messy, but that could be the reason

In the checkUserDuplicate function it counts the amount of DIVs within a scope of classes. If there is no classes or DIVs the count is 0, and passed on to the for loop and creates a recursive loop.

Related

Why does the code return the number of iterations that executed over the actual value?

I'm studying Javascript, I came across a typical basic for loop that was structured like this:
var myArry = [];
for (var i = 0; i < 10; i += 2){
console.log(myArry);
}
This I understand, it will return the array as a whole with the values of i specified in the counter.
However I then pasted the following code out of curiosity. To see if i'd get the same result, which was what I assumed bring. However what I got was how many iterations happened before the loop ended?
```console.log(myArry.push(i));```
I know this is trivial, but I just want to understand how the language interprets the above line as the amount of times the for loop iterated before it ends.
Is the above line of code showing how many times push is executed, or is it some other abstraction I'm missing?
Any clarification is greatly appreciated.
Thank you.
Array.push returns the number of items in the array after that push is completed. it returns the equivalent of Array.length().
See ref hre
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push

getBody always returns null in Apps Script even though that's how I think it should be written

My code is intended to make editing easier in Google Docs, but doesn't quite work and returns getBody null. I've already tested setting "body" as a variable, but that doesn't quite work. Due to how inexperienced I am with Javascript, it's hard to wrap my head around why exactly getBody returns null. So, it'd help me for the future if you knew where I'm going wrong with this.
function myFunction() {
var searchResult
searchResult =
DocumentApp.getActiveDocument().getBody().findText("very",searchResult)
Logger.log(searchResult)
while (searchResult !== null)searchResult.getElement().asText().setAttributes(searchResult.getStartOffset(),searchResult.getEndOffsetInclusive(),"#FF000")
searchResult =
DocumentApp.getActiveDocument().getBody().findText("very",searchResult)
}
function highlightProblem() {
var words = ["very","so","totally","really"]
words.forEach(findText)
}
function onOpen(){
DocumentApp.getUi().createMenu('everythingisnotfine.avi').addItem('Higlight Words That Make You Sound Like a Dandy', 'higlightProblem').addToUi()
}
Your body is not null. Your first problem is in this line
searchResult = DocumentApp.getActiveDocument().getBody().findText("very", searchResult)
you have findText("very", searchResult) while you do not have the variable searchResult. As per documentation this requires a range class (read here)
Next up is the whole mess here
while (searchResult !== null)
searchResult.getElement().asText()
.setAttributes(searchResult.getStartOffset(),
searchResult.getEndOffsetInclusive(),
"#FF000"
)
I did some formatting to better see the whole while loop. First of all, this is an endless loop, because it will keep repeating as searchResult is never changed inside of the loop so this step is either skipped or will continue endlessly. Next up is this particular method:
.setAttributes(searchResult.getStartOffset(),
searchResult.getEndOffsetInclusive(),
"#FF000"
)
Please read up on the method here as you are using it incorrectly. You are providing a string to the method, where it expects an object. In the same documentation page scroll down to the next method, without the offsets, it shows an example of how attributes should be formatted.
Next we move outside of the loops. This seems to be pointless
searchResult = DocumentApp.getActiveDocument().getBody().findText("very",searchResult);
perhaps you meant it to be done inside the while loop? Because essentialy what you are currently doing is
Set searchResult from document.
Log searchResult object
Set searchResult attributes (since that looks like hex color code, I assume you wish to color the code). Do this while searchResult is not null.
Set searchResult from document
End
If this was meant to be inside the while loop then you need to add { after while and } after the last action you wish to happen in 1 iteration of the while loop.

Javascript: Array not shifting, multiple setTimeout functions (JSON)

I'm really stuck on this javascript question!
So I'm making a web page that will be completely animated (so it can be used for display for example in a television). That animation will be configurable by the user (stored in a database).
Right now, I've already made the code to store the configuration and to get the configuration (I do an AJAX call and save the configuration in an array of json objects) and everything is as it should be.
The problem is in the animation in which I go through the array and use setTimeout function to create animations. To iterate through the array I rotate it
(I use array.push(array.shift()) according to the answer here).
The first time the intervalmaster function is used, everything goes according to plan, but when the function is called again I need to rotate the array once more (because of the last animation) and the array just doesn't rotate!
Bellow I've left a portion of the code that I'm using that reproduces the problem I'm getting. I've also added the array jsonanima with some possible values (In reality the array is probably much bigger and with higher values).
I really don't understand what is happening, I've also considered that this could be a problem of the multiple setTimeout functions because I've read somewhere (couldn't find the link, sorry!) that is not really advised to use multiple setTimeout.
If that's the case is there any other way to do this?
Thank you in advance!
EDIT: Thanks to the comment from mplungjan I've realized that if change the console.log(jsonanimate) to console.log(JSON.stringfy(jsonanima)) it outputs the correct values (the json array rotated). This got me even more confused! Why do I need to JSON.stringfy to get the array in the correct order?!
Anyway, can't test this with the full code now as I'm not in the office, tomorrow I'll give more feedback. Thank you mplungjan.
EDIT2: Finally solved my problem! So the thing was the call to the function recursivegroup (recursivegroup(0);), this call was made before I rotated the array, so when restarting the animation the array would still have the incorrect values and every sub-sequential value was wrong.
A special thanks to mplungjan and trincot for the comments that helped me debug this problem.
Bellow I leave the code corrected so anybody with the same problem can check it out.
jsonanima=[{"VD":5,"A":10,"diff":0.25},{"L":7,"IE":8,"diff":0.25}];
function intervalmaster(flag){
function recursivegroup(index)
{
if(index==0)
{
//animateeach(jsonanima,0);
}
setTimeout(function(){
//HERE IT WORKS
jsonanima.push(jsonanima.shift());
console.log(JSON.stringify(jsonanima));
//animateeach(jsonanima,0);
//removed the if statement, since it was irrelevant as mplungjan noted
recursivegroup(index+1);
},(jsonanima[0]['diff'])*60*1000);
}
//Changed this
//recursivegroup(0);
var mastertime=0;
for(var key in jsonanima)
{
mastertime+=(jsonanima[key]['diff']);
}
console.log(mastertime,flag);
console.log(JSON.stringify(jsonanima));
if(flag==true)
{
jsonanima.push(jsonanima.shift());
console.log(JSON.stringify(jsonanima));
}
//changed to here
recursivegroup(0);
masterinterval=setTimeout(function(){intervalmaster(true)},mastertime*60*1000);
}
intervalmaster(false);

Adding delay in few items

I just got a little problem. So I've got array of div names and I want to add them class for half a second and then remove in order they are set. So first shows after a second and disappears after half a second, and next after second etc. I loop through array and nothing really happens :/
Please help me with this function :/
function showAndRepeat(){
for(var z=0;z<clickNext.length;z++){
console.log(colors[clickNext[z]]);
setTimeout(function(){$(colors[clickNext[z]]).addClass(colorNames[clickNext[z]])},1000);
setTimeout(function(){$(colors[clickNext[z]]).removeClass(colorNames[clickNext[z]])},1500);
}
}
Assuming the jQuery code is working fine.
Try this:
function showAndRepeat(){
for(var z=0;z<clickNext.length;z++){
console.log(colors[clickNext[z]]);
(function(zee){
setTimeout(function(){$(colors[clickNext[zee]]).addClass(colorNames[clickNext[zee]])},1000);
setTimeout(function(){$(colors[clickNext[zee]]).removeClass(colorNames[clickNext[zee]])},1500);
})(z);
}
}
Simply, create a closure.
for loop is a sync operation whereas setTimeout is an async. therefore by the time setTimeout executes, the for loop have already ran and the latest value of z is fed into setTimeout call.

Function inside an if statement inside a function

I currently have the following code:
function someFunctionThatRunsOnce(identifier){
if (var < 1){
runSomeOtherFunction(identifier);
var++;
}
}
The variable will not increment when var < 1 is true. It stays at 0 and does not increase. When I move the variable increment statement about runSomeOtherFunction(), it then works fine.
What I want to know is:
1) Why is this happening? Why is running the second function disabling the increment?
2) Is there a better way to do this? I need to run this function this way exactly once, under a set of very specific circumstances. The function that runs is used elsewhere using different parameters for (identifier).
Please keep things simple I am a super noob and do not know jQuery and only really simple use of JS.
a big issue is that "var" is not a valid variable name, it's a reserved keyword.
you can easily use your wrapper as a namespace to store the state of being called or not:
function someFunctionThatRunsOnce(identifier){
if (!someFunctionThatRunsOnce.spent){ //not run yet?
someFunctionThatRunsOnce.spent=true; //set as run
runSomeOtherFunction(identifier); //run real workload
}
}
this lets you avoid global variables and curtails the possibility of runSomeOtherFunction() accidentally changing the state of the spent tracker property.

Categories

Resources