why Javascript showing output with setTimeout function sync and async? - javascript

for(var i = 2;i >= 1;i--) {
setTimeout(function (i) {
console.log(i);
},1000);
console.log("hii");
}
This code gives me output as
hii
hii
undefined
undefined
Where as after using setTimeout in below format gives different output
for(var i = 2;i >= 1;i--) {
setTimeout(print(i),5000);
console.log("hii");
}
function print(i) {
console.log(i);
}
This code gives me output as
2
hii
1
hii
I don't understand why in second case code is executing synchronously.

Because there you have called the print function, it's not passed as a callback. In this situation, it will complete the execution of print function and then pass the return value as first argument to setTimeout.
This is what you are trying:-
for(var i = 2;i >= 1;i--) {
setTimeout(print(i),5000);
console.log("hii");
}
function print(i) {
return function(){console.log(i)}
}

In the first example, you are passing a function that takes a single parameter, i to setTimeout , but setTimeout does not pass any arguments to that function (or any function for that matter) when it calls it. Hence i is undefined in that function and so undefined is outputted.
In the second example, you are calling print, and passing the result to setTimeout. But print is executing immediately, so that's why a number is outputted before "hii" each iteration.

for(var i = 2;i >= 1;i--) {
setTimeout(function (i) {
console.log(i);
},1000);
console.log("hii");
}
Javascript has a function-level scope and not a block-level scope. so when you call the setTimeout inside the for loop like below:
setTimeout(function (i) {
console.log(i);
},1000);
what happens is a local variable i is introduced which has not been set to any value and hence it returns undefined in JS.
in your second snippet the callback gets executed and returns value which is printed on screen

Related

JavaScript Lexical environment

I heard that every function remembers(?) the lexical environment where the function had created.
In this code, The function function () { console.log(i);},
I want to know where this function had been created. If some function is a parameter of other function, where is the created(?)/generated point?
function countSeconds(howMany) {
for (var i =1; i <= howMany; i++) {
setTimeout(function () {
console.log(i);
}, i * 1000 );
}
};
In this code, The function function () { console.log(i);}, I want to know where this function had been created.
This function is defined as a function expression. Such an expression is evaluated at runtime, much like an expression { y: x*x } would be evaluated at runtime. But in this case the evaluation result is a function object. And that function is then passed as argument to setTimeout. This means there are just as many functions created as there are iterations of your for loop.
Now, even though the function expression is evaluated at the moment setTimeout is executed, this does not mean that the body of the function is executed at that same time. It is not. It will only be executed when the timeout expires. At that time the function body executes, and at that time only it will evaluate expressions used in that code, such as variable i. In your example, the variable i will already have reached the value howMany+1, because that for loop already ran to completion before the timer expired, and the callback got called.
If that is something you want to avoid, then use a separate variable i for each iteration of the for loop. With let instead of var you create such distinct variables, which only live inside the for loop's block. And so then each of the function expressions will reference its "own" i:
function countSeconds(howMany) {
for (let i =1; i <= howMany; i++) {
setTimeout(function () {
console.log(i);
}, i * 1000 );
}
};
countSeconds(10);
If some function is a parameter of other function, where is the created(?)/generated point?
Like all arguments to a function call, they're evaluated right before the function is called. You can rewrite this with two temporary variables into the equivalent
function countSeconds(howMany) {
for (var i=1; i<=howMany; i++) {
const __arg1 = function() {
console.log(i);
};
const __arg2 = i * 1000;
setTimeout(__arg1, __arg2);
}
}
The function is created when the function expression is evaluated.
(Also notice that this code has the famous closure in a loop problem.)
I dont understand what you mean?
You mean where the function console.log() ist defined?
class console {
log(text) {
[I dont know]
}
}
Then you can make "console.log()" to call the function "Log" from Claas console? Did you mean that?

executing a block of code at a certain exact time in javascript

I want to execute a block of code (which includes recursive setTimeout) at a certain exact time in javascript.By writing get_current function i get the current time and with setInterval method with 1 mili second interval i compare the current time( fetched from get_current function) with my desired time and if that condition satisfies i execute a block of code recursively. i test my code with console messages and i understand that only once this code is executed and if statement is checked only once.
could any one help me doing that???
var dateString;
var delay=1500;
function get_current() {
var mydate = new Date();
var mili_real = mydate.getMilliseconds();
var hour_real=mydate.getHours();
var minute_real=mydate.getMinutes();
var second_real=mydate.getSeconds();
if(minute_real<10)minute_real="0"+minute_real;
if(hour_real==0)hour_real="12";
if(second_real<10) second_real="0"+second_real;
if(mili_real<10)mili_real="00"+mili_real;
else if(mili_real<100) mili_real="0"+mili_real;
dateString=hour_real+""+minute_real+""+second_real+""+mili_real;
}
setInterval(checkStart(),1);
function checkStart() {
get_current();
if (dateString == 145412578) {
var timerId = setTimeout(
function request() {
console.log("request"+delay);
if(delay<1600){
delay++;
} else {
delay--;
}
timerId=setTimeout(request,dealy);
}, delay);
} else {
console.log("waiting to start");
}
}
First, let's take a look at the docs: It says that setInterval takes two main parameters. There are optionally additional parameters to pass to the function when it's called, but let's ignore those and focus on the first two parameters. The second parameter is the time in milliseconds, which is clear for you. The first parameter is a function. Let's see your call
setInterval(checkStart(),1);
You pass checkStart() as your first parameter. It's a function call. There is no return in that function, which means that it "returns" undefined. So, your code above is functionally equivalent with the following:
checkStart();
setInterval(undefined,1);
So, the solution should be to pass the function instead its result to setInterval:
setInterval(checkStart,1);
and as a result, checkStart should be regularly called.

Two sources which have 'callbacks' in the for loop create different results

I can not understand why #1 and #2 produce different results.
To my basic understanding 4,4,4,4 is correct, since callbacks exist in the callback queue (you can check this at http://latentflip.com/loupe/).
//#1
function func1(a,b,func){
var k = a + b;
for (var i =0;i<k;i++){
func(i);
}
}
function func2(param){
setTimeout(function() {
console.log(param);
}, 10);
}
func1(1,3,function(result){
func2(result);
});
result of above #1 >>> 0, 1, 2 ,3
//#2
function func1(a,b){
var k = a + b;
for (var i =0;i<k;i++){
setTimeout(function() {
console.log(i);
}, 10);
}
}
func1(1,3);
result of above #2 >>> 4, 4, 4, 4
In the second example you are calling the wait function within the for loop itself, which causes the JavaScript to execute the queued console.log commands only after the value of i has finished incrementing.
In the first example, the function with the log statement is called externally, and only returns to the for loop once the output has been printed. The callback correctly prevents further execution of the loop until each call to the external function has been completed.
The first function prints the i var.
The second one increases i while it keeps going in the for loop, and when the timeout ends i=4, so it prints 4 times 4.
This because it is an async function.
The right way to do what you want to is the first one, calling another function to force the console.log(i) and not keep going until the func2 ends.

Return a function from the anonymous wrapper?

I am trying to undrstand the code
for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
}
from here http://bonsaiden.github.com/JavaScript-Garden/#function.closures
I understood this method :
for(var i = 0; i < 10; i++) {
(function(e) {
setTimeout(function() {
console.log(e);
}, 1000);
})(i);
}
Can anyone please help me by explaining the first one?
I will try to explain how I understands the first one,
first i is 0,
setTimeout is called,
self calling function "function(e)" is called with i=0,
Im stuck!! what happens when this function returns a function?
All the first one does is return a function that will be called after the timeout happens.
The purpose of it is to create a sub-scope for each iteration of the for loop so that the incrementing i isn't overridden with each iteration.
More explanation:
Lets take this apart into two different pieces:
for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
}
This is the first piece:
for(var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i); //9-9
},1000);
}
Now, when you run this loop, you will always get console.log()'s that contain 9 instead of 0 to 9. This is because each setTimeout is using the same reference to i.
If you wrap the setTimeout part of that in an anonymous function, it creates a scope for each iteration allowing each setTimeout to have it's own i value.
for(var i = 0; i < 10; i++) {
setTimeout((function(i) {
return function() {
console.log(i); // 0-9
}
})(i), 1000)
}
The outer function inside the setTimeout gets executed immediately with an i of 0 for first iteration, 1 for second, etc. That function then in turn returns a function which is the function that setTimeout uses. A function is being generated and returned for each iteration of the loop using a different value for i.
Both end up with the same result: a setTimeout is called with a function to invoke, which writes a number from 0 to 9 on the console. Both use nested functions to get the current value of i into a closure so you don't end up logging 10 9's.
The first code chooses to have a function returning the function that setTimeout will call. The second changes the nesting order so that the closed-over function invokes setTimeout itself. The net effect is the same.
Other than stylistic reasons and personal choice, I don't see a reason to choose one over the other.
"Can you please check the updated question specifying where im getting confused"
OK, here's the long explanation. Remember that the first parameter to setTimeout() needs to be a reference to the function that you want executed after the specified delay. The simplest case is to just name a function defined elsewhere:
function someFunc() {
console.log("In someFunc");
}
setTimeout(someFunc, 100);
Note there are no parentheses on someFunc when passing it as a parameter to setTimeout because a reference to the function itself is required. Contrast with:
setTimeout(someFunc(), 100); // won't work for someFunc() as defined above
With parenthese it calls someFunc() and passes its return value to setTimeout. But my definition of someFunc() above doesn't explictly return a value, so it implicitly returns undefined - which is like saying setTimeout(undefined, 100).
But it would work if changed someFunc() to return a function instead of returning undefined:
function someFunc() {
return function() {
console.log("In the function returned from someFunc");
};
}
So now (at last) we come to the code from your question:
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
Instead of referencing a function by name and calling it as someFunc(i) it defines an anonymous function and calls it immediately as (function(e) {})(i). That anonymous function returns another function and it is that returned function that becomes the actual parameter to setTimeout(). When the time is up it is that returned function that will be executed. Because the (inner) function being returned is defined in the scope of the (outer) anonymous function it has access to the e parameter.

Javascript: Could not really understand the function return

It is maybe incredibly easy but I couldn't solve what was going on.
function doSomething(a)
{
var num=10;
return setTimeout(
function(){ a(num); }, 1000);
}
The only thing that actually confuses me is the a(num) part. What actually it does?Reminder: I really am asking because I'm not familiar with the javascript syntax.
When the function doSomething() is executed it is passed the parameter a,
a is also some function that is then called when setTimeout() expires after 1 second,
then calling the function a() passing the argument called num
Example usage:
// call doSomething() passing the test() function as an argument
doSomething(test);
// takes a number as an argument and shows an alert with that value
function test(number)
{
alert(number);
}
// takes a function as an argument that will perform a 1 second timeout then execute the function called a
function doSomething(a)
{
var num=10;
return setTimeout(
function(){ a(num); }, 1000);
}
It calls the function referenced by the variable a, using the value referenced by the variable num as an argument.
setTimeout returns a timeoutID which can be used to cancel it using clearTimeout, so if you run doSomething a lot of times you will get different integer numbers which represent different timeoutID.
In your case a must be a function so you can call it using the parameter num
Example:
function doSomethingElse (justANumber) {
return justANumber + 1;
}
// Here you call your function
doSomething(doSomethingElse);
// or another special case
doSomething(function (justANumber) {return justANumber + 1;});

Categories