Ok, I am pretty new to jquery and Javascript.
I was reading about callback on w3school and it gives two examples.
Example1:
$("button").click(function(){
$("p").hide("slow",function(){
alert("The paragraph is now hidden");
});
});
Example2:
$("button").click(function(){
$("p").hide(1000);
alert("The paragraph is now hidden");
});
I understand that in first case alert will ONLY be executed after hide() function has finished.
However in second example it is possible that alert might execute before hide finishes.
This has caused some confusion in my understanding. Like for example is it possible that alert('hey') might get executed before alert which comes before it (one with mathmatical calculation) in following case..
$("button").click(function(){
alert(1+2+(3*4)..blah..blah);
alert('hey');
});
OR
in this case..
$("button").click(function(){
fn1();
fn2();
});
function fn1(){
for(var i=0;i<100;i++){
$('table').append(blah);
}
}
function fn2(){
alert('hey');
}
Is it possible that 'hey' might appear before fn1 has finished appending?
If so do I need to write every thing as callback??
To answer your question: No.
The key is that certain javascript functions are asynchronous. These really only come in two common categories:
XmlHttpRequest (i.e. AJAX) calls, where the browser goes out to the network to get something, and it lets the script continue running while it gathers the response.
timeouts and intervals, where you tell the browser to call some code after a delay. The script will continue unimpeded and then, when the time arises, the timeout code will run.
In your examples:
$("p").hide("slow",function(){
alert("The paragraph is now hidden");
});
The hide function in jQuery is timeout based. So your script does not have to wait for the animation to complete before it gets on with its business. jQuery provides a callback parameter so you can choose to have something happen after the animation completes if you want.
So in this example:
$("button").click(function(){
$("p").hide(1000);
alert("The paragraph is now hidden");
});
It is wrong to say the alert "might" execute before the hide finishes. Unless your code is executing so slowly that it takes more than 1 full second for an alert to show, it will execute before the hide completes. 1000ms is an eternity to a line of javascript.
$("button").click(function(){
alert(1+2+(3*4)..blah..blah);
alert('hey');
});
In this example, there is nothing asynchronous about the code. alert is a so called blocking call, meaning nothing happens in the script until you dismiss the alert. So you are guaranteed that the alerts will appear in order no mater how complex you make the parameter.
In fact, the complexity of the parameter has no bearing because it will evaluate in full before the resulting string is passed to the alert function.
So long story short, unless you're doing Ajax, setTimeout and setInterval, or using a third party library (which should document its behavior) your code will execute in order.
No. The reason the alert() occurs first in example 2 is because the hide() call is asynchronous. The hide() function is fired, but this has a 1000 millisecond delay. The alert() is fired instantly afterwards, not 1000 milliseconds afterwards, therefore it appears that the alert() was fired first.
In example 1 the alert() fires only when the hide() has completed, as this uses a callback function.
When using alert or confirm in Javascript, the browser is forced into a synchronous (existing or occurring at the same time) process where everything (even the loading of another page) halts until the user dismisses the dialog.
So when you alert something, browser will halt execution of other functions.
But jQuery hide and other animation functions are asynchronous (not existing at the same time) so that browser will go to next line without waiting for them.
For ex.
$(document).ready(function(){
fn1();
fn2();
});
function fn1(){
for(var i=0;i<100;i++){
$('body').append("<div>blah</div>");
console.log("blah!");
}
}
function fn2(){
console.log("Hey!");
}
Here hey will be logged after blah (100 times) as the browser waits for f1() to complete.
DEMO
But if you try something like:
$(document).ready(function(){
fn1();
fn2();
});
function fn1(){
for(var i=0;i<100;i++){
if(i%10==0)
{
fn2();
alert(true);
}
console.log("blah!");
}
}
function fn2(){
console.log("Hey!");
}
Then alert will show its way of working.
Also in jQuery:
$("p").hide("slow",function(){
// This is the call back function and not others.
});
The callback will be executed when any async or sync function first of all executes its tasks.
no it is not possible, for functions the JavaScript does them line by line but all in once, BUT it returns the result of the first one after giving the result of the second one! but as for the other example, it is obvious that hide() is going to take much longer to give the requested respond comparing to alert which is a browser built in function and that's why the alert appears to be working before hide(), I don't know the exact time that it takes to do these things but if you google it, you can learn them too if you need to!
BTW when an alert() pops up, it shuts down the whole javascript codes while it's on, just for you to know. ;)
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
Suppose I have this code:
$('#button').on('click', function () {
$('#status').text('doing some work....');
somethingThatTakes20Seconds('#status');
});
Here, somethingThatTakes20Seconds will be executed before the "doing some work" statement. While I understand the statement itself creates a DOM event which gets placed into the event queue and waits until the stack is clear to execute, what I don't get is how it's doing it (on a high level). Is the .text method asynchronous, in the same way like setTimeout() is (just with .text you don't take any callback, or is the callback auto-generated, basically some code that updates the DOM)?
The text() method is not asynchronous. $('#status').text('doing some work....'); will execute before somethingThatTakes20Seconds('#status');.
You can define your somethingThatTakes20Seconds() method to register a callback - which internally adds a listener to the JavaScript engine. When the listener "hears" something - ie. an AJAX request is completely or an user performs an action, it adds an item to the message queue.
This is where the event loop comes in. The event loop takes this message queue item and then calls the callback function associated with it.
No, .text() method is not asynchronous.
JavaScript only executes your code each line in sequence. It does not wait until each line execution is completed to execute the next line.
In your code, basically what you're doing is:
Change the #status text to doing some work.....
Run somethingThatTakes20Seconds() function.
It's just impossible for your function to do the 2nd function for 20 seconds, and then run the 1st one considering how fast it is to run the 1st function.
Consider the following sample,
function addTextOne() {
$('#result').append('This is text 1.\n');
}
function addTextTwo() {
$('#result').append('This is text 2.\n');
}
$(function() {
$("#testBtn").on('click', function() {
setTimeout(addTextOne, 1001);
setTimeout(addTextTwo, 1000);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="testBtn">
Test
</button>
<br/>
<textarea id="result" cols='70' rows='30'></textarea>
Note: The code sample basically executes addTextOne before addTextTwo on button click. But, addTextTwo finishes earlier than addTextOne.
The browser will not render the DOM to show the "doing some work..." message until after the function returns. Assuming your somethingThatTakes20Seconds function does not return for 20 seconds, you will not see that message for 20 seconds. You probably want to do something like this:
$('#button').on('click', function () {
$('#status').text('doing some work....');
setTimeout(function () { somethingThatTakes20Seconds('#status'); }, 10);
});
This will allow the DOM to be rendered before starting the long-running process.
For example: https://jsfiddle.net/9eq85udz/2/
I have created a method to let the user wait for certain period of time. (waiting window)
function hideMe()
{
document.getElementById('rotate').style.visibility= "hidden";
}
function showMe()
{
document.getElementById('rotate').style.visibility= "visible";
}
function wait()
{
showMe();
setTimeout(hideMe, 2000); // To show certain window for 2 seconds
}
But the window just flashes even I increase the time longer. It doesn't improve a lot.
Why is that?
What is the alternative method?
Well, I can't use jQuery in this project, sorry.
UPDATE
Sorry... I use visibility instead of display but it still can't work.
I found out that I will send some requests to server after the command wait() and it influences setTimeout().
like:
wait();
httpReq();
If I add alert("after wait()")
like:
wait();
alert("after");
The alert won't be executed after the wait();
in your code you are using
document.getElementById('rotate').style.display= "visible";
where display does not have "visible" property.
You either have to use "block","inline".
or you can also set display property to blank.
document.getElementById('rotate').style.display= "";
Check if this helps.
As per OP's comment
setTimeout is not synchronous command. if you want something to be execute out after the setTimeout is executed. You have to add it to setTimeout function. For Eg
setTimeout(function(){hideMe();alert("test");}, 2000);
I am confused as to why the following html is not working.
I would expect it to keep sending alerts but it stops after one.
Furthermore, the "left fn" alert never occurs!
Can anyone explain this to me?
I am using html5 with javascript in firefox on ubuntu.
<!DOCTYPE html>
<script>
function alertme() {
alert ("in fn");
}
while (true) {
window.setTimeout(alertme(), 3000);
alert("left fn");
}
</script>
A few probable issues:
alertme() is being called immediately and its return value is instead being passed to setTimeout().
To fix this, you can pass alertme as a reference (without the calling parenthesis):
setTimeout(alertme, 3000);
However, this will then conflict with JavaScript's (primarily) single-threaded nature.
The setTimeout()s, being asynchronous, simply start a timer that expires no less than 3 seconds from now. But, they require that the one thread is eventually not busy for the delayed task to be performed.
However, the while (true) {}, being synchronous and indefinite, will keep the thread busy until all execution is stopped and will never allow the timeouts to perform their tasks. So, you will never see "in fn".
John Resig has a good write up on timers: http://ejohn.org/blog/how-javascript-timers-work/
How exactly to fix the code depends on the intent.
while (true) {
window.setTimeout(alertme, 3000); //setTimeout wants a function, not the return value of the function
alert("left fn");
}
btw, have fun with klicking all the messageboxes away...
I have this code where I am using two javascript functions that do some manipulating for me. One function does some calculation but calls the other function before doing anything else. When the other function returns to it, it is supposed to do the final calculations.
The problem: The call to the other function is not executing properly. Even before the second function returns the first function executes completely.
code:
firstfunction{
secondfunction();
do something more nothing related to second
}
secondfunction(){
setTimeout(func1(){
do something independently
then call func1 depending on some condition
},time);
}
second function is used somewhere else also and is working fine.
My question:
I used this code thinking that the first function will not execute before second function executes completely. Is it right? Isn't this the way javascript functions should run? The first function executes completely before second returns. I am sure of this because after second returns the position for the graphic first is supposed to place that graphic on screen. But the first executes completely and the graphic is placed awkwardly on screen and viewer can see it moving to right position given by the loop of second. Is setTimeout causing this problem?
Please help.
This happens because you use setTimeout. setTimeout will make it asynchronous. Execution of second function will be completed after setting the interval and execution-flow will go back to first function. So you have to split your first function and make a third function which will have the final steps. This third function has to be invoked from the setTimeout handler.
function firstfunction(){
secondfunction(params);
}
function secondfunction(params){
setTimeout(func1(){
do something independently
then call thirdfunction depending on some condition
},time);
}
function thirdfunction(params){
do something more nothing related to second
}
In this method you have to pass everything as parameters from one function to other.
You can also do this in a different way by making third one a callback function. This way you can make everything in the scope of firstfunction available for thirdfunction.
function firstfunction{
secondfunction(thirdfunction);
function thirdfunction(){
do something more nothing related to second
}
}
function secondfunction(callback){
setTimeout(func1(){
do something independently
then call callback depending on some condition
},time);
}
"Even before the second function returns the first function executes completely."
No, in fact the second function returns immediately after it calls setTimeout() - it does not wait for the timeout to occur. The func1() function that you pass to setTimeout() will be called later after the specified timeout delay, but meanwhile execution continues with whatever follows the setTimeout() call (in this case the end of the function follows, so it returns to the first function and then the rest of the first function continues). To put it another way, setTimeout() does not pause execution.
If you need something to happen after the timeout you need to either place it in the function you pass to setTimeout() or call it from that function.