JavaScript for loop in a function - javascript

I am currently stuck with a javaScript for loop.
The situation is like this, in my program there is a function which returns true/ false value in every 200 ms.
The function, which I am currently trying to code, should obtain the value from the above function ( for the ease of reference, I would name it as, function1) and store it in an array.
I am trying to use a for loop to store those values in an 8 element array.
Shown below is my code,
function myFunction1(imagestatus) //
{
var statusArray = ["","","","","","","",""];
for (var i = 0; i <= statusArray.length - 1; i++)
{
statusArray[i] = imagestatus;
}
}
Now, during the first execution of the for loop, it will assign the 0th element of the array, true or false. And during the second execution also it will do the same which is no good.
The task I expect to do is, when the function1 returns its value to myFunction it must store it in the 0th element. Then when it returns again, if its as same as the value in 0th element, store it in the 1st element, if not same, then take a different action.

Start with an empty array:
var array[];
then use:
array.push(data);
To add each datum to the right end of the array.

Sounds like a number of things need to happen. First, you are asking for a callback function. Second, you need to move the status array to the global scope.
var statusArray = ["","","","","","","",""];
function myFunction1(imagestatus, callback, differentAction) //
{
var i = 0;
// if its as same as the value in 0th element,
while (statusArray[i]==imagestatus)
{
i++;
}
if (i<statusArray.length && i>0)
{
// store it in the 1st element
statusArray[i]=imagestatus;
if (typeof(callback)=="function")
{
callback();
return;
}
}
// if not same, then take a different action
if (typeof(differentAction)=="function")
{
differentAction();
return;
}
}

Related

Trying to increment an integer in an Array

Good Evening,
I am trying to increment an integer that I have index position of '0' in my array, each time my function gets called. I have the variable added with .push, but then I just want to add one to that. I am trying to use indexof(), I have also tried findIndex(). Below is my code
const addFunction = async () => {
var storage_array = await AsyncStorage.getItem(ASYNC_STORAGE_KEY);
try {
if(storage_array) {
storage_array = JSON.parse(storage_array);
let flow_complete = 0;
var foundIndex = storage_array.indexOf(flow_complete);
console.log(foundIndex);
storage_array[foundIndex] = flow_complete++;
await AsyncStorage.setItem(ASYNC_STORAGE_KEY, JSON.stringify(storage_array));
console.log('THIS IS THE ASYNCSTORAGE', storage_array);
} else {
flow_complete = 0;
console.log('Storage array is empty')
}
} catch (error) {
console.log(error);
}
}
Following the re-wording of the issue with your comment:
[...] the objective is to take the number ‘0’ that’s in the 0th position of the array and increment it by 1 each time the function runs
The first issue I see is that you may be misusing the indexOf function. That will not give you the index of an array, but instead the position of a particular value of an array.
Example:
const arr = [9, 2, 7, 14]
const index = arr.indexOf(9) // This will be 0, because the index of the number 9 in this array is 0
const otherIndex = arr.indexOf(7) // This will be 2, because the index of the number 7 in this array is 2
So, for you to access the element in the 0th position, you will want to do arr[0]. So in your code you will want to do the following:
storage_array = JSON.parse(storage_array);
let flow_complete = 0;
// notice there is no need to get the `indexOf` 0 since you do want the position 0
storage_array[0] = flow_complete++;
Now... This will have a second problem which is your usage of the incrementation operator ++. Although this will increment the flow_complete variable, it does not return it to set storage_array[0] as you intend to do so.
To fix this, all you have to do is increment flow_complete prior to assigning it to storage_array[0]. It will look something like this:
let flow_complete = 0;
flow_complete++;
storage_array[0] = flow_complete
However, if my interpretation of your comment above is correct, there is one more problem, which you are assigning flow_complete to storage_array[0] each time the function runs. flow_complete is set to 0 as you can see in your own block of code within the scope of your addFunction, so this means it will always go back to 0 every time it is run.
Going back to your original comment, you want to increment the value in the 0th index of storage_array, not flow_complete itself, correct?
If this is the case, you can completely get rid of the flow_complete variable and instead increment storage_array[0]. This will make your if-block look as follows:
if(storage_array) {
storage_array = JSON.parse(storage_array);
storage_array[0]++;
await AsyncStorage.setItem(ASYNC_STORAGE_KEY, JSON.stringify(storage_array));
console.log('THIS IS THE ASYNCSTORAGE', storage_array);
}

How to update a variable that is returned from a function?

I've been trying to write a go back function. What this function will do is it'll store last two ID number that has been generated and append when there is a new one, delete the first one.
I have this function which creates the IDs and plays the video with that ID.
function newVideo(){
let rando = Math.floor((Math.random() * 3970) + 1);
document.getElementById("vsrc").src = "https://raw.githubusercontent.com/ondersumer07/vinematik-videos/master/vid/" + rando + ".mp4";
document.getElementById("videoEl").load();
return rando;
}
I am returning the rando to use it outside this function, and I can access it outside the function, the problem is, the variable outside the function is not updating everytime newVideo() run.
The code for that goes like this:
let rando = newVideo();
let vidids = [];
if (vidids.length < 2) {
vidids.push(rando)
console.log("added")
} else {
vidids.shift()
console.log("deleted")
};
Basically what this does is to get the returned rando value and push it to the vidids array, delete the first one if there is more than two but it won't, it does not update the let vidids = []; array for some reason. I need it to update everytime the newVideo() function ran.
Also, I want the if to add if there is less then two items in that array and delete from the start of the array if there is more than two items in it. Not really sure if that'll work too.
I can't seem to figure out how to do this, am I doing this whole thing wrong or is there still hope for this function? How am I supposed to write that function?
Edit: I've changed the vidids.length part yet the problem still occur because let rando = newVideo(); doesn't update.
In order to keep the last two Items of an array, you can use something like this.
let vidids = [];
function addToArray(item, array){
array.unshift(item);
return array.slice(0,1);
}
//test
vidids = addToArray(newVideo(), vidids);
vidids =addToArray(newVideo(), vidids);
vidids =addToArray(newVideo(), vidids);
vidids =addToArray(newVideo(), vidids);
vidids =addToArray(newVideo(), vidids);
console.log('Done');
You've made a small mistake that caused your code to not work properly.
The IF condition is intended to check the length of the 'vidids' array,
What actually happens is that it compares the array referance instead of it's length
To fix the issue, add .length after 'vidids' inside of the IF condition.
....
if (vidids.length < 2) {
.....
I figured it out. Basically what I did is storing every number the algorithm creates and then taking one before the last.
Which goes like this:
The algorithm for creating random numbers:
function randomNum() {
let rando = Math.floor((Math.random() * 3970) + 1);
return rando;
};
Then I put this function in a variable:
let videoid = randomNum()
I had another variable called videoids which is above and outside of the randomNum function and is an array:
let videoids = []
After that I stored every number I created with videoid inside videoids by pushing it(This push needs to be inside your function):
videoids.push(videoid);
Okay so I stored all the numbers this way. Now I should take one before the last so I can go to previous video. So I needed to create a function, I used this function which was created by Tadeck, in this thread.
if (!Array.prototype.last) {
Array.prototype.last = function() {
return this[this.length - 2];
};
};
Now I can put that inside of my prevVideo function which looks like this:
function prevVideo() {
document.getElementById("vsrc").src = srcRaw + videoids.last() + ".mp4";
document.getElementById("videoEl").load();
videoids.push(videoids.last());
}
Note: Don't forget to push videoids.last inside your videoids otherwise you can only go to your previous number for once.

value of the index changes after getText() inside a for loop - PROTRACTOR

In the code below, I'm using a repeater to get the values from ng-repeat and getting the column by cat.name which gives me an array of all the cat names. So I'm doing a for loop to get to a particular name, say Meow, I want to store the index value, so that I can validate whether the corresponding row, the cat's age to be equal to 10. The 2 console.log of index inside the for loop results in different values, the first one ranges from 0-10 (considering the length of the array as 10) and the next always results in 10. It logs "10" 10 times. Now, I cannot get the index to validate the corresponding row, since i is always 10. Can someone correct me where I'm going wrong and also answer me with the modified code. I guess I'm going wrong in chaining the promise
element(by.repeater(cat in cats).column(cat.name)).then(function(fields) {
for (var i in fields) { // promise returns an array fields
console.log(i); // values range from 0 to length of the fields(say 10)
fields[i].getText().then(function(fieldValue) {
console.log(i); // values are always 10 (i.e the length of the array)
if(fieldValue === 'Meow') {
var catAge= element(by.repeater('cat in cats').row(i)).element(by.model('cat.age')); // row(i) always gives the last value
expect(catAge.getAttribute('value')).toBe('10');
}
})
}
});
The issue come from below snippet, the first console.log() is executed sync, but the second console.log() will be executed async, because it inside getText().then(), as we know all Protractor api is async and return a Promise.
for (var i in fields) {
console.log(i);
fields[i].getText().then(function(fieldValue) {
console.log(i);
So the actual execution procedure of above for loop should be like this:
when i=1
first console.log() execute done, it print out 1
fields[i].getText() execute done, it return a Promise,
and push the promise into Protractor control flow,
actually getText() not to read the text from page,
because it's execute async.
when i=2
first console.log() execute done, it print out 2
fields[i].getText() execute done, it return a Promise,
and push the promise into Protractor control flow,
actually getText() not to read the text from page,
because it's execute async.
....
when i=10
the loop end,
you get 1, 2 .. 9, 10 printed out
Protractor control flow get a promise queue
Now Protractor control flow start to execute the promise queue
Protractor push out the fist promise in queue
Important!!! the i=10 now
fields[i].getText() will be fields[10].getText()
so you will get fields[10].getText() for 10 times
Option 1) use javascript closure as Jamines comment said, a little changes on your current code
element(by.repeater(cat in cats).column(cat.name)).then(function(fields) {
for (var i in fields) {
console.log(i);
(function(index){ // change part
fields[index].getText().then(function(fieldValue) {
console.log(index);
if(fieldValue === 'Meow') {
var catAge= element(by.repeater('cat in cats').row(index)).element(by.model('cat.age'));
expect(catAge.getAttribute('value')).toBe('10');
}
})
})(i); // change part
}
});
Option 2 use Protractor filter()
element(by.repeater(cat in cats).column(cat.name)).then(function(fields) {
for (var i in fields) {
console.log(i);
var matchedIndex = -1;
fields
.filter(function(item, index){
if( matchedIndex > -1) {
// means had found the matched one, directly return false to
// skip read text from page to reduce exection time
return false;
}
else {
return item.getText().then(function(name){
if(name === 'Meow') {
matchedIndex = index;
return true;
}
return false;
})
}
})
.then(function(){
console.log('matchedIndex: ' + matchedIndex);
var catAge= element(by.repeater('cat in cats').row(matchedIndex)).element(by.model('cat.age'));
return expect(catAge.getAttribute('value')).toBe('10');
});
}
});

Return and log of the same variable don't match

I have an array named bars that contains the active id numbers of progress bars. I want to go through this array to find the first value that does not match its index (for finding the lowest available ID). My (apparently incorrect) solution is as follows:
var bars = [0,1];
function getNewBarID(counter) {
var i = counter || 0; //sets i to counter value if it exists, or to 0 if it doesn't
if (bars[i] == i) {
++i;
getNewBarID(i);
} else {
console.log(i);
return i;
}
}
getNewBarID();
When I run this (in a node console and in chrome js console) it logs 2 to the console and returns undefined, while it should return 2.
what!?
edit: when the function is run with an empty array, it both returns and logs 0 (more what!?)
Probably:
return getNewBarID(i);
But to be honest it should rather be:
const newBar = bars.find((el,i) => el !== i) || bars.length; //newBar contains the result...
or a bit longer using a good old for loop:
function getNewBarID(){
let i = 0;
while(bars[i] === i) i++;
return i;
}
Try it
That is because you first run
getNewBarID();
where
if (bars[i] == i)
is true. From there you make the next call, yes, but the first call executes without a return value. You get a return value eventually, however first you executed twice without returning anything. Just add a return to the if-case:
return getNewBarID(i);

Check if item already exists in json array by matching ID

So I've this shopping cart, as JSON.
[{"tuote":{"id":"2","name":"Rengas 2","count":16,"price":"120.00"}},{"tuote":{"id":"1","name":"Rengas 6","count":"4","price":"25.00"}},{"tuote":{"id":"4","name":"Rengas 4","count":"4","price":"85.00"}}]
Formatted here.
So, I want to prevent from having the same value in there twice, and match them by their ids.
This is my current solution (buggy as a cockroach, doesn't really do the job), as the only time it works is when the matching value is first in the JSON string.
for (var i = 0; i < ostoskori.length; i++) {
if (ostoskori[i].tuote.id == tuoteID) {
addToExisting(tuoteID, tuoteMaara); //this doesn't matter, it works.
break //the loop should stop if addToExisting() runs
}
if (ostoskori[i].tuote.id != tuoteID) {
addNew(tuoteID, tuoteNimi, tuoteMaara, tuoteHinta); //this doesn't matter, it works.
//break
//adding break here will stop the loop,
//which prevents the addToExisting() function running
}
}
ostoskori is the json if you're wondering. As you can probably see, for each item the JSON has inside it, the more times addNew() will run.
So basically, if the JSON has a value with the same id as tuoteID, addToExisting() should run. If the JSON doesn't have a value same as tuoteID, run addNew().
But how?
You could use some to check if the id already exists. The beauty of some is:
If such an element is found, some immediately returns true.
If you're catering for older browsers there's a polyfill at the bottom of that page.
function hasId(data, id) {
return data.some(function (el) {
return el.tuote.id === id;
});
}
hasId(data, '4'); // true
hasId(data, '14'); // false
So:
if (hasId(data, '4')) {
addToExisting();
} else {
addNew();
}
Fiddle

Categories

Resources