I am confused about the example in http://dreamerslab.com/blog/en/javascript-callbacks/
function do_a(){
// simulate a time consuming function
setTimeout( function(){
console.log( '`do_a`: this takes longer than `do_b`' );
}, 1000 );
}
function do_b(){
console.log( '`do_b`: this is supposed to come out after `do_a` but it comes out before `do_a`' );
}
do_a();
do_b();
results
`do_b`: this is supposed to come out after `do_a` but it comes out before `do_a`
`do_a`: this takes longer than `do_b`
and the author's explanation is "However javascript is an event driven language. If do_a takes longer than do_b, the result of do_b comes out first than do_a;". I am still not quite clear, please explain in details, or please point me to some specific material, thank you,
setTimeout says to execute its function after 1 second. Each function returns immediately, while setTimeout executes after that time.
In actuality, do_a() and do_b() are executing in order. But the results of setTimeout are independent of do_a or do_b.
Further, that is a poor example of callback function execution since setTimeout has nothing to do with a callback. A better example is as follows:
var a = function(callback){
setTimeout(function(){
callback();
}, 1000);
console.log('1');
}
var b = function(callback){
setTimeout(function(){
callback();
}, 2000);
console.log('2');
}
a(function(){
console.log('3');
});
b(function(){
console.log('4');
});
do_a() and do_b() are executed immediately one after the other. When do_a() executes, it starts a timer which prints the output in 1000ms (after the output of do_b() has been printed)
So they do execute in order, it just doesnt wait for a response
Related
In this article which I was referred to the following statement is made:
Callbacks are a way to make sure certain code doesn’t execute until other code has already finished execution.
The article then goes on to illustrate this with an example:
function doHomework(subject, callback) {
alert(`Starting my ${subject} homework.`);
callback();
}
doHomework('math', function() {
alert('Finished my homework');
After this the articles states:
As you’ll see, if you type the above code into your console you will get two alerts back to back: Your ‘starting homework’ alert, followed by your ‘finished homework’ alert.
The implication seems to be that by using a callback the desired order of code execution has been ensured. That is you start your homework before you finish it. However, I feel I may have misunderstood the whole point of the article and therefore still do not understand callbacks and asynchronous code because when I slow down the first part of the doHomework function using setTimeout() the code executes (or at least returns) in the opposite order:
function doHomework(subject, callback) {
setTimeout(function(){
console.log(`Starting my ${subject} homework.`);
}, 500);
callback();
}
doHomework('math', function() {
console.log('Finished my homework');
});
The result I get from that is:
steve#Dell ~/my-app $ node app.js
Finished my homework
Starting my math homework.
});
I am using node here (hence console.log() replaces alert()) but I do not think that is relevant.
It seems to me I have missed something quite fundamental and need to try and access what it is that I am trying to understand before I then try and understand it.
Any assistance on this journey would be greatly appreciated.
After getting great feedback I think the homework analogy was not helpful so I am now using the first code example in the article I referenced. The article gives this code:
function first(){
// Simulate a code delay
setTimeout( function(){
console.log(1);
}, 500 );
}
function second(){
console.log(2);
}
first();
second();
The above returns 2 then 1 in the console.
I tried (without success) to reverse the return order to 1 then 2 with this:
function first(callback){
setTimeout(function(){
console.log(1);
}, 500);
callback();
}
function second(){
console.log(2);
}
first(second);
The answer I got from Cleared (before it was edited) was to put the callback() inside the setTimeout() function. He used the homework example but here it is with this example:
function first(callback){
setTimeout(function(){
console.log(1);
callback();
}, 500);
}
function second(){
console.log(2);
}
first(second);
I think that is closer to what I am imagining the article was getting at. It seems to make sense although I guess the precise context of what you are doing and what you want to happen determine what is right or wrong.
In general, the call to the callback is not at the end of the function, but rather after you have done the important things.
So if I understand your question, the doHomework-function should start doing homework (which takes time, in this case 500ms), and then the homework is finished. So the important things in your case is the console.log('Starting my ${subject} homework.'); which "takes 500ms" (since this is the time you need to do the homework).
Therefore, you should put the call to the callback right after console.log('Starting my ${subject} homework.');, i.e.
function doHomework(subject, callback) {
setTimeout(function(){
console.log(`Starting my ${subject} homework.`);
callback();
}, 500);
}
doHomework('math', function() {
console.log('Finished my homework');
});
Generally, you would call the callback function when you are finished doing whatever it is you are doing.
So you have the code inside and outside your setTimeout function backwards.
function doHomework(subject, callback) {
console.log(`Starting my ${subject} homework.`);
setTimeout(function(){
console.log(`Finished my ${subject} homework.`);
callback();
}, 500);
}
What exactly is callback?
Callback meaning function-in-function like recursive.
Let me give you an example:
Every day we eating then sleeping. But in JS code, JS is an impatient language unlike PHP. This is the example code:
// Consuming 3s to eating(just an example, not really 3s)
function eating() {
setTimeout(function() {
console.log('Eating...');
}, 3000);
}
// Then go to sleep
function sleep() {
console.log('Z..Z..Z');
}
eating();
sleep();
But you sleep immediately after...(When we run the code it runs the sleep first then eating())
To assure that everything works in order, meaning you only go to bed when done eating. So we need the eating() to tell when it's done to start the sleep():
// Consuming 3s to eating(just an example, not really 3s)
function eating(callback) {
setTimeout(function() {
console.log('Eating...');
callback() // the function which will be proceeded after "Eating..."
}, 3000);
}
// Then go to sleep
function sleep() {
console.log('Z..Z..Z');
}
// call the function
eating(function() {
sleep();
});
Yeah! Right now I think you can use callback in your code!
Where you can see callback?
You can see it in every JQuery code:
$("#hide").click(function(){ //the click() function call the function inside it which is callback
$("p").hide();
});
$("#show").click(function(){
$("p").show();
});
Callbacks in Javascript are used in asynchronous programming, where you can't ensure that the code above is running before the code below, like loading files from a server asyncronous.
The problem is, that with normal sequential programming, you can not ensure, that the data you fetch is fully loaded when the programm is running (i.e. if you run the script, one time the variable could be setted, another time it could be undefined, cause async task is still running), so you set a callback function, which gets connected to different states, ie. success or error on ajax call. The difference to normal programming flow is, your programm does not stop till it has loaded the data (or in your case, the timeout doesnt pause your program, the code afterwards is computed and the timeout can run of anytime, if you dont use a fix value).
So, to ensure that your code will run when the needed logic finishes, you have to pass a callback function, which is executed when the needed state is fulfilled (i.e. success/error on loading tasks, or a timeout is "finished".
The homework example IMO isnt the best sample, cause it doesnt touch the real use cases, as it always "waits" 500ms.
In your example the problem is, your "callback" is out of the "asyncronous" part of code, so its executed directly after starting the timeout, even if the timeout still is "running". Maybe your thinking of SetTimeout is the problem, in my javascript beginnings I thought its more like "pause for 500ms", but its "execute the scoped code after waiting for 500ms out of the normal code flow"
Here are some more informations, I can recommend the whole page, even if your not javascript noob ;)
https://javascript.info/callbacks
I recreated this example (from link given below) to understand callbacks. The problem is that the callback gets executed before the parent function 'first()' finishes. setTimeout works fine but callback doesn't wait until after the above . If i comment out line 1 and 3 of first() i.e. the timeout part, then it logs in the right order.
<script type="text/javascript">
function second() {
console.log("second/callback function")
}
function first(callback){
setTimeout(function(){
console.log("first function")
}, 1000 );
callback();
}
first(second);
If this is working fine and i misunderstand the nature of setTimeout, then please give another example where the callback can be seen waiting.
Link:
https://codeburst.io/javascript-what-the-heck-is-a-callback-aba4da2deced
Note: I know very little JS, was actually working in PHP, so kindly give a simple explanation. Thanks
It appears that you misunderstand how setTimeout() works. This tool called Loupe by Philip Roberts may help you understand. I've taken your code placed it into the tool which will allow you to visualise what is actually happening - link to Loupe
When you use setTimeout, that function provided as the first parameter is delayed for the number of milliseconds provided in the second parameter (in your example, this is 1000). The rest of your code will continue to execute in order until this timeout has lapsed.
If you want your callback function to execute after the given timeout: you can actually just write it such like:
setTimeout(callback, 1000) <- Since callback is already a function, you don't need to wrap it in another function unless you wish to do other operations before calling the callback.
Update 1 (2018-10-26):
function second() {
console.log("second/callback function")
}
function first(callback){
console.log("first function")
setTimeout(callback, 1000);
}
first(second);
Here you are calling "callback" synchronously which means first function will wait for second(callback) function to be completed and then proceed with it's execution. To understand it better I have put console log at other places as well. Pls try below and see if you now have better understanding for the same
function second() {
console.log('second method started')
setTimeout(() => console.log("second function executed"), 1000)
console.log('second method finished')
}
function first(callback){
console.log('first method started')
setTimeout(() => console.log("first function executed"), 1000 );
callback();
console.log('first method finished')
}
first(second);
Is it possible to make a function 'idle' for a couple of seconds while it is being executed?
I tried with
setTimeout( function(){
$("#nytLevel").hide();
} , 3000 );
But the rest of the function would just executed.
Below the setTimeout I start a function
function timer(){
myVar = setTimeout( function(){
console.log("SLOW");
} , 10000 );
}
but when 10 seconds have passed it'll console log "SLOW", but it should console log it 13 seconds after because I've put a setTimeout to 3 seconds.
setTimeout() just schedules something to run in the future and the rest of your Javascript continues to run. It does not block further Javascript execution. This is often called an "asynchronous" operation. It runs in the background and will call a callback sometime in the future when it has completed its work. It is also referred to as "non-blocking" because it does not block the rest of your Javascript execution.
Anything you want to not run until the setTimeout() fires must be put inside the setTimeout() callback or called from there.
// define function
function timer(){
myVar = setTimeout(function() {
console.log("SLOW");
}, 10000);
}
// schedule first timer
setTimeout(function() {
$("#nytLevel").hide();
// now start second timer
timer();
}, 3000);
It's worth mentioning that jQuery has a .delay() method that works with animations and other functions put in the queue and it can sometimes streamline your code. In the case above, you could do this:
$("#nytLevel").delay(3000).hide().delay(10000).queue(function(next) {
console.log("SLOW");
next(); // keep the queue moving in case there's something else in the queue
});
Please note that .delay(xxx) only works with jQuery methods that themselves use the queue (such as animations) or with methods you put in the queue yourself using .queue() (as I've shown above).
setTimeout() is an asynchronous function, meaning that code will not pause until the setTimeout() time is completed. If you want code to be delayed along with the setTimeout(), you can put the other code inside of the initial setTimeout()
setTimeout( function(){
$("#nytLevel").hide();
myVar = setTimeout( function(){
console.log("SLOW");
} , 10000 );
} , 3000 );
I wouldn't recommend this, but you could fashion a recursive function to do what you wanted, using a flag to dictate before or after timeout. In the below example you'd call it like this runAfterTimeout() or runAfterTimeout(false)
function runAfterTimeout(run) {
if (! run) {
console.log('about to wait 10 seconds');
setTimeout(function(){runAfterTimeout(true)},10000);
return;
}
console.log('this section runs after 10 seconds');
setTimeout(function(){$("#nytLevel").hide();},3000);
}
Fiddle: https://jsfiddle.net/m9n1xxra/
Bear in mind, timeouts are not 100% accurate. The engine will look for an appropriate break in execution to execute what you want, but if the engine is in the middle of something else, that will execute first.
I understand that Javascript does not have a delay(500) method, which would delay execution for 500 milliseconds, so I have been trying to get around that by using setTimeout and setInterval.
for(var i =0; i< 10; i++){
/* Animation Code */
var doNothing = function(){var m =5;}
setTimeout(doNothing, 50);
}
However, this does not seem to work. I essentially want some code that stops the execution for n milliseconds and then continues execution.
Practically speaking, you can't do this. Deal with it and find a callback-based way instead. Typically this means putting everything that should happen after the delay in the callback itself.
For example, you can't do this to make baz wait:
foo();
setTimeout(function() {
bar();
}, 500);
baz();
so you do the only thing you can:
foo();
setTimeout(function() {
bar();
baz();
}, 500);
The setInterval() Method wait a specified number of milliseconds, and then execute a specified function, and it will continue to execute the function, once at every given time-interval.
Syntax
window.setInterval("javascript function",milliseconds);
The window.setInterval() method can be written without the window prefix.
The first parameter of setInterval() should be a function.
How to Stop the Execution?
The clearInterval() method is used to stop further executions of the function specified in the setInterval() method.
Syntax
window.clearInterval(intervalVariable)
The window.clearInterval() method can be written without the window prefix.
To be able to use the clearInterval() method, you must use a global variable when creating the interval method:
myVar=setInterval("javascript function",milliseconds);
Then you will be able to stop the execution by calling the clearInterval() method.
good refrence
If you came from the language/framework/API background, where you could suspend the execution with something like Sleep, or process user input synchronously with something like DoEvents, it won't work in JavaScript.
There is no way you can block the JavaScript event loop with something like this, for a good reason: UI responsiveness. In JavaScript, everything is asynchronous. You can use setTimeout to do something upon a timer event, but the user is still able to access the UI between the timer events or even navigate away from the page.
To address your code fragment, what you are looking for is called an asynchronous state machine. It allows to preserve the state of the code between stop/continue (in your case, it's the state of the animation, although i variable is also a part of it):
(function()
{
var i = 0;
var nextStep = function()
{
if (i<10)
{
/* Animation Code */
i++;
setTimeout(nextStep, 500);
}
}
nextStep();
})();
It will be much easier to code when all browsers support the new yield keyword:
http://pag.forbeslindesay.co.uk
On a side note, some other answers suggest using setInterval. There is a subtle but important difference between delay and interval. Delay is the time between two steps. Interval is the time since the previous step started. If each step of animation takes 200ms, and you use the interval of 500ms, the actual delay between two steps will be 300ms, not 500ms as probably expected.
setInterval() - executes a function, over and over again, at specified time intervals
To pass a function as a string, be sure to append the function name with parentheses.
window.setInterval("someFunction()", 5000);
When passing a function pointer, do not include the parentheses.
window.setInterval(someFunction, 5000);
var timer_id=setInterval(doNothing,500);
If you want to stop the execution
make the timer_id variable global
clearInterval(timer_id);
Much cleaner and readable code would be if you use RxJS
Here is an example:
Rx.Observable
.interval(1000)
.take(10)
.subscribe((x) => console.log(`${x}: ${new Date().toLocaleTimeString()}`))
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.lite.min.js"></script>
interval - is a time delay between your animation calls. In my example
it's 1000ms
take - number of times to execute subscribe - is function
that will be called every 1000ms for 10 times (in your case it will be
your animation code)
Here some something that could help.
function delay( s , callback )
{
var fct_ref = "tmp_" + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 6).toUpperCase();
var tmp_fct = ( callback !== undefined ) ? callback.toString().match(/^[^{]+\{(.*?)\}$/)[1] : "";
document.getElementsByTagName("body")[0].insertAdjacentHTML("beforeend","<div id='"+fct_ref+"' style='background-color:transparent;color:transparent;position:absolute;top:"+window.scrollY+"px;left:"+window.scrollX+"px;opacity:1;transition:all "+s+"s'>-</div>");
var func = new Function("return function transition"+fct_ref+"(e){ e.target.removeEventListener('transitionend' , transition"+fct_ref+", false ); "+tmp_fct+" ; document.getElementById('"+fct_ref+"').parentNode.removeChild(document.getElementById('"+fct_ref+"')); };")();
document.getElementById(""+fct_ref).addEventListener("transitionend", func , false );
document.getElementById(""+fct_ref).offsetHeight;
document.getElementById(""+fct_ref).style.opacity="0";
}
delay(1, function() { console.log("ANIMATION_1"); } );
delay(3, function() { console.log("ANIMATION_3"); } );
delay(5, function() { console.log("ANIMATION_5"); } );
I am getting into sort of confusion here. Please go through the below code,
<script>
setInterval(function1,3000);
setInterval(function2(),3000);
function function1() {
console.log("Function1 called....");
}
function function2() {
console.log("Function2 called....");
}
</script>
As you can see I have two setInterval functions one calls function like function1 and another function2(). The output of first is perfect that gets called every 3sec and first call after 3sec. But second one gets called without the delay i.e function2.
I guess that () might be doing things there but I'm not sure about what I'm missing there. I just want to know what is happening there.
setInterval(function1,3000); instructs the JS engine to execute the function function1 every 3 seconds.
setInterval(function2(),3000); instructs the JS engine to run function2 once, then run the return value every 3 seconds. This return value is empty.
For a bit of fun try
function function2() {
console.log("Function2 called....");
return "function3();"
}
function function3() {
console.log("Function3 called....");
}
setInterval(function2(),3000);
Edit
In reponse to #harsha's comment: What do I mean by "run the return value"
setInterval(function2(),3000); will trigger the following workflow:
Initiate executing function2() (execute it, because it the brackets are given).
function2 runs to completion, then returns.
In your OQ, there is no return value from the function so it is null
The return value of my function2 is the string "function3();"
This return value is now inserted into the setInterval() call
The OQ version results in setInterval(null, 3000);, which does nothing every 3 seconds
My version results in setInterval("function3();", 3000), which calls eval("function3();"); every 3 seconds, which in turn runs function3 every 3 seconds.
In the second setInterval you are executing it right away and plugging the value returned by that function into setInterval.
For example,
setInterval(a(), 5000);
function a(){
return function(){
console.log("Executed!");
};
};
a() executed and returning the function into setInterval. You should see the console is writing Executed every 5 seconds.
This is just like math:
f(x) = x + 1
g(x) = 2
f(g(2)) = g(x) + 2 = 4
You replace g(2) with whatever it returns
(you replace a() with the function in this case)
http://jsfiddle.net/DerekL/39wNn/
The () makes the function get executed immediately in the second case. In the first case, just the pointer to function which gets executed later as the call back function.