I have a small for loop, but it is skipping even count , what am I missing ?
var i = 0;
function myLoop() {
setTimeout(function() {
//code below
console.log(Date() + ' and count is ' + i++);
//code above
if (i < 20) {
myLoop();
}
}, i++)
}
myLoop()
i++ is equal i = i + 1; But when you call console.log(i++), first thing wil be console.log with Old value, and after increment your value.
You raise the timeout with every iteration by on millisecond. Is that what you wanted?
https://www.w3schools.com/jsref/met_win_settimeout.asp
setTimeout(function, milliseconds, param1, param2, ...)
var i = 0;
function myLoop() {
setTimeout(function() {
//code below
console.log(Date() + ' and count is ' + i++);
//code above
if (i < 20) {
myLoop();
}
}, 1)
}
myLoop()
Your i++ in the console.log statement is modifying your i variable.
i++ is equal to i = i + 1.
Replace i++ with i, which will evaluate correctly as postfix increment will return the value before the modification which would just be i.
This works:
var i = 0;
function myLoop() {
setTimeout(function() {
//code below
console.log(Date() + ' and count is ' + i);
//code above
if (i < 20) {
myLoop();
}
}, i++)
}
myLoop()
Can also be done by adding another variable for the console.log
var i = 0;
var t = 0;
function myLoop() {
setTimeout(function() {
//code below
console.log(Date() + ' and count is ' + t++);
//code above
if (t < 20) {
myLoop();
}
}, i++)
}
myLoop()
You have i++ twice in your code. First you increment it when you call setTimeout at the bottom of your code and then you display the uneven value via console log and increment i. Change your logging to
console.log(Date() + ' and count is ' + i);
Related
function updateScreen() {
var textOutput = "";
setScreen("yellowScreen");
for (var i=0; i < finalColor.length; i++){
var newIndex = i+1;
textOutput = (((textOutput + newIndex +". NAME: " +finalName[i] + ", "
+ "scientific name is") + finalScientificName[i] + ", " + "this bird is
")+ finalConservationStatues[i] + "and they eat ")+ finalDiet[i]+"\n\n";
}
setText("yellowOutput", textOutput);
console.log(textOutput);
}
onEvent("yellowButton", "click", function( ) {
yellowFilter();
upDateScreen();
});
the function yellowFilter prevents anything else to run
function yellowFilter() {
for (var i = 0; color.length; i++) {
if (color[i] == 'Yellow' ) {
appendItem(finalColor, color[i]);
appendItem(finalDiet, diet[i]);
appendItem(finalConservationStatues, conservationStatus[i]);
appendItem(finalScientificName, scientificName[i]);
appendItem(finalName, Name[i]);
console.log(finalColor);
}
}
}
is there anything wrong with these functions the update screen function doesn't run if the yellowFilter runs but yellowFilter needs to run so that upDateScreen can run properly
Without actually going through anything I see one error immediately:
for (var i = 0; color.length; i++)
The second statement in a for loop needs to be a conditional
An example of simple nested for loop:
for (let i=0; i<=2; i++) {
for (let j=0; j<=1; j++){
console.log("i is: " + i);
console.log("j is: " + j);
console.log("---");
}
}
Nested for loop with delay:
for (let i=0; i<=2; i++) {
for (let j=0; j<=1; j++){
task(i,j);
}
}
function task(i,j) {
setTimeout(function() {
console.log("i is: " + i);
console.log("j is: " + j);
console.log("---")
}, 1000 * i);
}
NOW MY QUESTION IS
How can I delay each loop seperately.
Current output (ignore the "---"):
i, j, delay, i, j, delay, ...
Desired output (ignore the "---"):
i, delay, j, delay, i, delay, j, delay ...
I tried things like below (but its returning a complete wrong output)
for (let i=0; i<=2; i++) {
for (let j=0; j<=1; j++){
taski(i);
taskj(j)
}
}
function taski(i) {
setTimeout(function() {
console.log("i is: " + i);
}, 1000 * i);
}
function taskj(j){
setTimeout(function() {
console.log("j is: " + j);
}, 1000 * j);
}
You could use Promise and async/await to handle sequential call
function taski(i) {
return new Promise(function (resolve) {
setTimeout(function () {
console.log("i is: " + i)
resolve()
}, 1000 * i)
})
}
function taskj(j) {
return new Promise(function (resolve) {
setTimeout(function () {
console.log("j is: " + j)
resolve()
}, 1000 * j)
})
}
async function execute() {
for (let i = 0; i <= 2; i++) {
for (let j = 0; j <= 1; j++) {
await taski(i)
console.log("delay")
await taskj(j)
console.log("delay")
}
}
}
execute()
Reference:
async function
Promise
Ok the thing is setTimeout works in it's own world that isn't limited by the for loops, or any other code for that matter, it doesn't actually "block" the current code at all, in the for loop you are just setting up a bunch of intervals, really fast one after the other (since the for loop doesn't stop or get delayed by the timeouts), which later execute in some unknown order when the time for each one individually runs out, which is not blocked or dependant on any of the other timeouts
If you want to keep relatively the same format you have now, but with delay blocking you can use await and promises and async functions
(async () =>
for (let i=0; i<=2; i++) {
for (let j=0; j<=1; j++){
await taski(i);
await taskj(j)
}
}
)()
function taski(i) {
return new Promise((rs) => setTimeout(function() {
res(console.log("i is: " + i));
}, 1000 * i));
}
function taskj(j){
return new Promise((rs) => setTimeout(function() {
res(console.log("j is: " + j)
}, 1000 * j));
}
You could try to to an asynchronous approach with async/await:
function sleep(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
(async function() {
for (let i = 0; i <= 2; i++) {
for (let j = 0; j <= 1; j++) {
await taski(i);
await taskj(j);
}
}
}())
async function taski(i) {
await sleep(1000 * i);
console.log("i is: " + i);
}
async function taskj(j) {
await sleep(1000 * j);
console.log("j is: " + j);
}
I actually want to update my previous question Javascript understanding return because the code below is quite similar to the previous one but since that question was answered already I decided to post this. The code of my previous questions works fine already but I want to satisfy some of my curiosities so I experimented the code and moved the return namePosition,
function positionIdentifier(name, nameArray) {
var namePosition;
for (i = 0; i < nameArray.length; i++) {
if (nameArray[i] == name) {
namePosition = function() {
alert("Your name is in position number " + (i + 1));
}
}
}
return namePosition;
}
name1Array = ["look", "sky", "walk", "kier"];
positionIdentifier("walk", name1Array)();
Why does it alert the wrong position (i+1)? Instead it alerts the final position which is the length of the array.
You forgot to use break statement here is correct code:
<script>
function positionIdentifier(name, nameArray) {
var namePosition;
for (i = 0; i < nameArray.length; i++) {
if (nameArray[i] == name) {
namePosition = function () {
alert("Your name is in position number " + (i + 1));
};
break;
}
}
return namePosition;
}
name1Array = ["look", "sky", "walk", "kier"];
positionIdentifier("walk", name1Array)();
</script>
That my friend is what is called a closure in javascript.
function() {
alert("Your name is in position number " + (i + 1));
}
When positionIdentifier function is invoked, i has the last value from the for loop.
To fix this you need to do this
function positionIdentifier(name, nameArray) {
var namePosition;
for (i = 0; i < nameArray.length; i++) {
if (nameArray[i] == name) {
/* now this will keep the correct value of i */
namePosition = (function(i) {
return function(){
alert("Your name is in position number " + (i + 1));
}
})(i)
/* now this will keep the correct value of i */
}
}
return namePosition;
}
Here is a working fiddle https://jsfiddle.net/uxyot51b/
I would like to do the something along the following:
for (var i = 0; i < 10; ++i) {
createButton(x, y, function() { alert("button " + i + " pressed"); }
}
The problem with this is that I always get the final value of i because Javascript's closure is not by-value.
So how can I do this with javascript?
One solution, if you're coding for a browser that uses JavaScript 1.7 or higher, is to use the let keyword:
for(var i = 0; i < 10; ++i) {
let index = i;
createButton(x, y, function() { alert("button " + index + " pressed"); }
}
From the MDC Doc Center:
The let keyword causes the item
variable to be created with block
level scope, causing a new reference
to be created for each iteration of
the for loop. This means that a
separate variable is captured for each
closure, solving the problem caused by
the shared environment.
Check out the MDC Doc Center for the traditional approach (creating another closure).
for(var i = 0; i < 10; i++) {
(function(i) {
createButton(function() { alert("button " + i + " pressed"); });
})(i);
}
Note that JSLint doesn't like this pattern. It throws "Don't make functions within a loop.".
Live demo: http://jsfiddle.net/simevidas/ZKeXX/
Create a new scope for the closure by executing another function:
for(var i = 0; i < 10; ++i) {
createButton(x,y, function(value) { return function() { alert(...); }; }(i));
}
http://www.mennovanslooten.nl/blog/post/62
You need to put the closure into a separate function.
for(var dontUse = 0; dontUse < 10; ++dontUse) {
(function(i) {
createButton(x, y, function() { alert("button " + i + " pressed"); }
})(dontUse);
}
Thise code creates an anonymous function that takes i as a parameter for each iteration of the loop.
Since this anonymous function has a separate i parameter for each iteration, it fixes the problem.
This is equivalent to
function createIndexedButton(i) {
createButton(x, y, function() { alert("button " + i + " pressed"); }
}
for(var i = 0; i < 10; ++i) {
createIndexedButton(i);
}
for(var i = 0; i < 10; ++i) {
createButton(x, y, (function(n) {
return function() {
alert("button " + n + " pressed");
}
}(i));
}
The anonymous function on the outside is automatically invoked and creates a new closure with n in its scope, where that takes the then current value of i each time it's invoked.
I would like to do the something along the following:
for (var i = 0; i < 10; ++i) {
createButton(x, y, function() { alert("button " + i + " pressed"); }
}
The problem with this is that I always get the final value of i because Javascript's closure is not by-value.
So how can I do this with javascript?
One solution, if you're coding for a browser that uses JavaScript 1.7 or higher, is to use the let keyword:
for(var i = 0; i < 10; ++i) {
let index = i;
createButton(x, y, function() { alert("button " + index + " pressed"); }
}
From the MDC Doc Center:
The let keyword causes the item
variable to be created with block
level scope, causing a new reference
to be created for each iteration of
the for loop. This means that a
separate variable is captured for each
closure, solving the problem caused by
the shared environment.
Check out the MDC Doc Center for the traditional approach (creating another closure).
for(var i = 0; i < 10; i++) {
(function(i) {
createButton(function() { alert("button " + i + " pressed"); });
})(i);
}
Note that JSLint doesn't like this pattern. It throws "Don't make functions within a loop.".
Live demo: http://jsfiddle.net/simevidas/ZKeXX/
Create a new scope for the closure by executing another function:
for(var i = 0; i < 10; ++i) {
createButton(x,y, function(value) { return function() { alert(...); }; }(i));
}
http://www.mennovanslooten.nl/blog/post/62
You need to put the closure into a separate function.
for(var dontUse = 0; dontUse < 10; ++dontUse) {
(function(i) {
createButton(x, y, function() { alert("button " + i + " pressed"); }
})(dontUse);
}
Thise code creates an anonymous function that takes i as a parameter for each iteration of the loop.
Since this anonymous function has a separate i parameter for each iteration, it fixes the problem.
This is equivalent to
function createIndexedButton(i) {
createButton(x, y, function() { alert("button " + i + " pressed"); }
}
for(var i = 0; i < 10; ++i) {
createIndexedButton(i);
}
for(var i = 0; i < 10; ++i) {
createButton(x, y, (function(n) {
return function() {
alert("button " + n + " pressed");
}
}(i));
}
The anonymous function on the outside is automatically invoked and creates a new closure with n in its scope, where that takes the then current value of i each time it's invoked.