1

this is just a question that will help me a lot figuring out some basic stuff.

i have a simple html page where i put 2 divs : #test and #testresult

this JQUERY which is writtn on a separate .js file is well included in the html page

$(document).ready(function () {
    var cssleft = $("#test");


    (function hhh() {

        cssleft.animate({
            left: "100px"
        }, 3000, function () {
            $('#testresult').html(cssleft.css("left"));
        }).animate({
            left: "-100px"
        }, 3000);

        cssleft.animate({
            width: "100px"
        }, 3000).animate({
            left: "10px"
        }, 3000);

        $('#testresult').html(cssleft.css("left"));

    })();
});

what i don't understand is the flow of execution.

i was expecting this code to go line by line :

1/ animate the #test div then write the 'left' value (100px) in the #testresult div . 2/ animate the #test div again. 3/ write the new value of 'left' (10px) in the #testresult div.

but what happens is that 1/ and 2/ go as expected only after the #testresult div gets modified by : $('#testresult').html(cssleft.css("left")); as if that line gets fired before the first two lines putting 0px in the #testresult div.

is there an explanation for this please ?

Pointy
  • 405,095
  • 59
  • 585
  • 614
hanachi
  • 121
  • 4
  • http://jsbeautifier.org – Pointy May 22 '14 at 00:42
  • 2
    The animation is asynchronous. The calls to `.animate()` *start* the process, but they don't wait until the animation is complete. – Pointy May 22 '14 at 00:43
  • i read on a [thread](http://stackoverflow.com/questions/2035645/when-is-javascript-synchronous) this "JavaScript is single-threaded, and all the time you work on a normal synchronous code-flow execution." i think that what happens here is just the opposite . maybe i am missing smething !! – hanachi May 22 '14 at 00:56

2 Answers2

2

In short what is happening is that animate is an asynchronous function. The line gets executed, yet the code does not wait for it to complete before executing the next line.

In order to do something when the animation is complete you should use the animations complete function callback as indicated in the docs here: http://api.jquery.com/animate/

Which is what you do in your code in the first animate. The second animate however does not use a complete function to run the line: $('#testresult').html(cssleft.css("left")); and therefore it will be executed instantly.

JanR
  • 6,052
  • 3
  • 23
  • 30
  • yes @JanR thank you i know about the fact that nearly every jquery function has the callback call possibility, then do i need to know which jquery methods are synchonous and which are not . is there a way to guess this too ? – hanachi May 22 '14 at 01:02
  • I guess the docs aren't always very clear about it, but I guess typically any function having a complete callback option can be assumed to be asynchronous – JanR May 22 '14 at 01:03
1

Javascript is, technically speaking, single threaded. But it does have concurrency, practically speaking. Or, from our human point of view, there are things that seem to "run at the same time". For example, two separate separate setIntervalss (a way to get a code to be run in intervals after a certain time) "animating" two separate objects "at the same time". And while that's running, we can have a button that, when clicked, outputs text.

Example

This is a good explanation of what really happens, javascript runtime wise. From the article, it is something like:

while(queue.waitForMessage()){
  queue.processNextMessage();
}

So let's say the initial block of code will be the first message. it sets up the onLoad and maybe some setIntervals. This will create new messages. When the page finally loads, it will be passed to the queue to be run. When a timeout, times out, it will also be sent to the queue to be run. But a message must finish before the next message will be run. So it looks like as if things are happening at the same time but, in actuality it's just short messages being run in a queue.

So the classic example will be, Example

setTimeout(function(){
   result.innerHTML+="1,";
},0); //wait time in ms

result.innerHTML+="2,";

setTimeout(function(){
   result.innerHTML+="3,";
},0); //wait time in ms

result.innerHTML+="4,";

Which will output 2,4,1,3,. So what happens is that the initial message will run, create two timeouts which will pass the functions as a message to the queue when the set time elapses (in this case, 0, which means it gets immediately sent to the queue.

It should be noted that the messages should be short. Perhaps it must. but that doesn't stop you from coding a really big for loop that traverses and processes huge 2D arrays from blocking your code (freezing everything) which, after a couple of seconds would lead to "This page is unresponsive" alert. Or in fact, as per the mozilla article, an alert() actually blocks. So i'll modify the examples and add to see them stop execution.

Also. Specific to your code, jQuery adds to the confusion in that jQuery automagically queues the animations up. Compare this jquery code:

$("#test").animate({"left":100},2000)
$("#test").animate({"top":100},2000)

With this plain javscript code;

var x=10;
setInterval(function(){
   x+=1
   test.style.left=x+"px";
},20)

var y=10;
setInterval(function(){
   y+=1;
   test.style.top=y+"px"
},20)

Granted, it's not exactly the same piece of code, which would involve callbacks. But I think it illustrates my point that, .animate has some magic queuing.

Actually, to close, it'll be good for you to look at promises pattern moving forward. which makes chaining these asynchronous events not be a crazy clusters of callbacks.

mfirdaus
  • 4,574
  • 1
  • 25
  • 26