javascript for loop executes only once - javascript

for(var i=0; i < imageFiles.length; i++)
{
console.log('index value : ' + i)
let item = imageFiles[i]
let file = item.getAsFile()
let oValue = await self.getOrientation(file)
console.log('orientation value : ' + oValue)
}
The for loop above is only executing once, could someone provide a solution that will make the loop iterate over all the files in the array ?

From within the parentheses, you defined the variable "i" with a value of 0. As a result, i++ will return 1 and also save it to "i". You said it's only executing once for some reason, clearly this is part of the issue.
Check to make sure any code related to this is written as intended.

Related

Code is getting stuck somewhere in a succession of for-loops and I'm not sure why

EDIT - I changed the code to correctly declare variables below but nothing seems to have changed
I've written code using a for-loop that has to satisfy a number of criteria before executing what's within it. The problem is that, somewhere along the way, the code is getting stuck inside one of the loops, causing the computer to crash.
I've tried breaking the loop but this doesn't seem to help.
function compareKeypoints(varifiedKeypoints) {
outer_loop: for (i = 0; i < varifiedKeypoints.length; i++) {
let initialKeypoint = varifiedKeypoints[i];
for (j = 0; j < varifiedKeypoints.length; j++) {
let comparisonKeypoint = varifiedKeypoints[j];
if (initialKeypoint.part != comparisonKeypoint.part) {
if (Math.abs(comparisonKeypoint.position.x - initialKeypoint.position.x) <= 20
&& Math.abs(comparisonKeypoint.position.y - initialKeypoint.position.y) <= 20) {
if (keypointsCompatible(initialKeypoint.part, comparisonKeypoint.part)) {
console.log("Activating part: " + initialKeypoint.part);
console.log("Activated part: " + comparisonKeypoint.part);
let keypointPair = {
point_1: initialKeypoint.part,
point_2: comparisonKeypoint.part
}
console.log("Pushing parts!");
activeParts.push(keypointPair);
console.log("breaking loop!");
break outer_loop;
console.log("Loop NOT broken!!");
}
}
}
}
}
if (activeParts.length > 0) {
console.log(activeParts);
}
}
function keypointsCompatible(keypoint_1, keypoint_2) {
var outcome = true;
if (activeParts.length > 0) {
compatibility_loop: for (i = 0; i < activeParts.length; i++) {
if (Object.values(activeParts[i]).includes(keypoint_1) && Object.values(activeParts[i]).includes(keypoint_2)) {
console.log(keypoint_1 + " and " + keypoint_2 + " are not compatible because they already exist as " + activeParts[i].point_1 + " and " + activeParts[i].point_2 + " respectively");
outcome = false;
break compatibility_loop;
console.log("Compatibility NOT broken!!");
}
}
}
console.log("Compatibility outcome is " + outcome);
return outcome;
}
The code is suppose to take two values in the same array and compare them. If a number of conditions are met, including if they're a certain distance apart from one another, they will be pushed into a secondary array. If the values already appear in the secondary array, which the keypointCompatible function is suppose to determine, the loop should either continue looking for other candidates or stop before being called again. For some reason, however, the code is getting stuck within the keypointCompatible function when it detects that the values have already appeared in the secondary array and the console will repeatedly print "Compatibility is false" until the browser crashes.
Working Solution
Use let or const instead of var or nothing. Your issue may be related to closures and variables reused between loops. Make sure you use let or const in your loops too. for (let i=0).
When you use let or const, the runtime will create a new instance every time the block or loop iterates. However, using var will reuse the internal allocation.
So what happens with the standard var is the multiple closures or loops each use the same instance of the variable.
Unless you want the var behavior, always use let or const.
Another Solution
Put a newline after the label compatibility_loop
Still Another Solution
The first function is pushing into activeParts. The second function is looping activeParts. This can go on forever, or longer than expected. Pushing into the array could possibly make the loop limit never reached.
Put a log on the length of activeParts in the second function to see if it is growing out of control.
Your code should be OK if varifiedKeypoints.length has reasonable value. And all internal variables are declared properly!
You have two loops (this inner can start at j=i+1 to save time and multiple calculations) with few conditions inside.
function compareKeypoints(varifiedKeypoints) {
outer_loop: for (let i = 0; i < varifiedKeypoints.length; i++) {
let initialKeypoint = varifiedKeypoints[i];
for (let j = i+1; j < varifiedKeypoints.length; j++) {
let comparisonKeypoint = varifiedKeypoints[j];

Not understanding what I'm missing in my forLoop function

I've been trying to figure this out by re-writing my forLoop multiple times, look online for example and even checked out MDN and gotten to the point I need someones help.
Now the test error I get is:
1) loops forLoop(array) adds `"I am ${i} strange loop${i === 0 ? '' : 's'}."` to an array 2
5 times:
ReferenceError: forLoop is not defined
My current code looks like this:
function forLoop(array){
var newArr = [];
for (var i = 0; i < array.length; i++){
if (i === 1) {
newArr.push("I am 1 strange loop.")
} else {
newArr.push(`I am ${i} strange loop${i === 0 ? '' : 's'}.`)
}
}
return newArr
}
Thinking process:
I need a loop to iterate the array being place.
I need a new array to input something each time we loop around.
Call a for loop. Set i to 0 as we will start from there.
Find the end point which is less than array.length
Place increment since we will be going up from 0 each time we loop.
Make if and else statement
Add if statement is true to the new array
Return the new array in the end
Is there something I'm not understanding or missing? Really can't seem to crack this.
For additional information about the test. The test for this problem is:
describe('forLoop(array)', () => {
it('adds `"I am ${i} strange loop${i === 0 ? \'\' : \'s\'}."` to an array 25 times', () => {
const [array, t] = makeArray()
const strangeArray = forLoop(array)
expect(strangeArray.length).to.equal(t + 25)
const testArray = strangeArray.slice(array.length)
for (let i = 0, l = testArray.length; i < l; i++) {
let s = i === 1 ? "I am 1 strange loop." : `I am ${i} strange loops.`
expect(testArray[i]).to.equal(s)
}
})
})
ReferenceError: forLoop is not defined means that the Javascript interpreter can't find the function "forLoop".
Possible causes:
The test and the function are not in the same file and you made a mistake while including the file which contains the function. Make sure you include your file with the function before the test file.
The test doesn't have access to the function because it's in a different scope of your application.
I tested the forLoop function myself and it worked for me. I don't think the problem is in the forLoop function.

Array reads, then stops- error: Cannot set property '0' of undefined

I'm trying to read in a csv string to a 2D array and for some reason it stops when it gets to the second iteration of the first loop.
Here's the Fiddle and the code:
$(document).ready(function(){
var lay = [[]];
document.getElementById("result").innerHTML = value;
bits = value.split(',');
console.log(bits.length);
elm = bits.length/4;
count=0;
console.log(bits[6]); //here it reads but won't assign to the array
for (i=0; i<=elm; i++)
{lay[i]=[];
console.log('i:'+i);
for (j=0; j<=4; j++)
{ console.log('j:' + j);
console.log('count:' + count);;
lay[i][j] == bits[count];
count = count + 1;
console.log('bit value:' + bits[count]);
}
}
console.log(lay[0][0]);
});
The value for the next element reads and displays, but when I try to assign the data to the array it errors out.
Fixed Code
added the redeclaration of the array in the first loop
That made the error go away.
Fiddle
Thanks!
Something wrong with u'r lay array I think.
Is this element set? lay[i][j]
I think I solved it
http://jsfiddle.net/hgm8r/3/
I've made two changes:
Declared the `lay' value outside the loop
var lay = Array();
And updated it at the start of the first loop
lay[i] = Array();
And now it runs without errors.

Am I loopy or is it localstorage...?

My goal: To clean up localstorage, by removing previously used items with a for loop.
Usually, I have a number of items, like so:
order-1356666288243 => {"cartID":2713329701836,"productName"...
order-1356666288243 => {"cartID":2713329701836,"productName"...
When I check how many items there are altogether, I get the correct zero-based amount:
console.log( localStorage.length );
Even when I do a for loop to write out the key and values, and console.log() a few other things, all is well:
for(var i=0, len=localStorage.length; i<=len; i++) {
var key = localStorage.key(i);
var value = localStorage[key];
console.log(key + " => " + value);
if(key != '' && key != null){
console.log( key.indexOf('order-') );
console.log(i + '. Key: ', key);
if(key.indexOf('order-') != -1){
console.log('The key to be removed is: ', key.toString());
localStorage.removeItem(key.toString());
}
}
console.log(i + ': ' + len);
}
Everything pretty much does what one would expect. However, this line executes only once when I run the script:
localStorage.removeItem(key);
or
localStorage.removeItem(key.toString());
In fact, I have to run the entire script as many times as there are items. So if I have, say 3 items, I need to run the loop 3 times to get rid of each item.
I'm perplexed: Where did I go wrong? All the console.log() stuff shows up 3 times (if I have 3 items and run the for loop once) . Out of despair, I even changed i < len to i >= len, but that doesn't solve the problem either.
Anyone?
The problem is that you are modifying a collection while you are traversing it. Always be careful when you do this.
In this particular case, the length of localStorage changes when you remove an item, so you end up skipping items.
You should either traverse localStorage backwards (last item to first item), or better yet you should do this in two passes: one pass to collect the keys to remove, and another pass to remove them:
Object.keys(localStorage)
.filter(function(key){return key.indexOf('order-')===0})
.forEach(localStorage.removeItem, localStorage);
Or if you need this to work in IE8 or FF3.x:
var delkeys = [], key, i, len;
for (i=0,len=localStorage.length; i<len, key=localStorage.key(i); i++) {
if (key.indexOf('order-')===0) {
delkeys.push(key);
}
}
for (i=0,len=delkeys.length; i<len, key=delkeys[i], i++) {
localStorage.removeItem(key);
}
I think the problem is that when you remove an item, it changes the length of the local storage. Try iterating from the length-1 down to 0 instead of from 0 up to the length. (By the way, the loop condition should have been i < len, not i <= len. With my suggestion, of course, it should be i >= 0.)
The loop should count down to prevent problems with deleted keys altering storage length. Try this for loop instead:
for( var i = localStorage.length; i--;){
//make sure to remove references to len in your code
}

Javascript: How to modify global variables within functions?

Below is the code I'm working on. I'm wondering why, when I change the variable ttt in the function, the changes do not stay outside of the function? I've declared it as var ttt = new Array; at the very top.
Also, why can't I use the variable i in the function?
code:
client.on('connection', function()
{
var sss;
var aaa;
console.log('Connected');
for (i = 0 ; i < 120 ; i++)
ttt[i] = 0;
for (i = 0 ; i < 9 ; i++)
{
client.getMatchHistory(434582, function(err, result)
{
sss = JSON.stringify(result);
var myObject = eval('(' + sss + ')');
console.log (myObject.object.data[i].object.value);
ttt[myObject.object.data[i].object.value]++;
});
}
for (i = 0 ; i < 120 ; i++)
console.log ("Record" + i + " Successes: " + ttt[i]);
});
As you pointed out, there are two separate problems with your code, and they're both somewhat related. First, ttt is being modified globally. The problem is that you're checking for the modifications before they happen. I suspect that client.getMatchHistory() is making an asynchronous call. There's no guarantee that all the asynchronous operations in the second for loop will be done executing by the time you execute the third for loop, where you read the array.
The second problem is one of scope, but it's not global scope that's your problem. Since client.getMatchHistory() is asynchronous, the callbacks will be called once the loop is done executing. Once the loop's done executing i will have a value of 10. Likely this is not what you intended. You need to create a callback generating function, that takes the value of i, and returns a function that can be used as a callback. Like this:
function make_callback(i) {
return function(err, result) {
// The body of your callback in here
};
}
And then you should use it like this in the body of the loop:
client.getMatchHistory(434582, make_callback(i))
This will capture the value of i in the current iteration and the generated callback will use that value when executed. That should fix your problem with i.
First of all, all globals variables are effectively 'window' object fields, so you can use window.ttt to be sure you are using global variables instead of local. This code should work, so did you try it in developer tool? what does debugger say about presence of such variable?
As for variable i: sure, you can use it, but it better to use it locally, defining 'var i;' on the top of the function to not spoil global namespace.
The client.getMatchHistory probably asynchronous request, you expect that after loop, you will have filled ttt array, to acheive this you have to make a handler which run after last loop step:
var afterloop=function() {
for (var i = 0 ; i < 120 ; i++)
console.log ("Record" + i + " Successes: " + ttt[i]);
}
for (var i = 0 ; i < 120 ; i++)
ttt[i] = 0;
var i_final=0;
for (var i = 0 ; i < 9 ; i++)
{
var i=i; //localise i
client.getMatchHistory(434582, function(err, result)
{
i_final++;
sss = JSON.stringify(result);
var myObject = eval('(' + sss + ')');
console.log (myObject.object.data[i].object.value);
ttt[myObject.object.data[i].object.value]++;
if (i_final>8) {afterloop();}
});
}
in the sample, i_final counts done requests, they can be done in random order, due to async, so you can't refer to i when deciding to run afterloop() , when i_final count to more than last executed request, you run function that should be executed after last request is done.
Note: please use global vars as less as possible, in your code you used global i without any reason

Categories

Resources