开发者

jQuery not executing in correct order?

I have recently started working with jQuery and today noticed a strange issue with how it's behaving for me. As I understand it, JavaScript is single threaded. So all of it's operations should run in a FIFO basis. However, this did not appear to be the case for me. P开发者_如何学运维lease consider the following.

SETUP is as follows

HTML:

3 divs

  • div#1 => contains header elements which can be clicked to execute the sort function

  • div#2 => contains the data that needs to be sorted

  • div#3 => contains an basic .gif which is used to notify the user that some operation is being performed

jQuery - contains the sort function which does DOM manipulation. Basically, it reads data from the HTML page, stores in a 2D array, and sorts the array. It then clears div#2 (data div) completely and rebuilds it, using data from the sorted array.

EXECUTION was expected to be as follows

  • user clicks one of the headers to trigger the sort function
  • sort function hides div#2 and shows div#3
  • sort function is executed
  • once sorting is completed, div#2 (data div) is shown and div#3 is hidden

However, here is what appears to happen

  • user clicks the headers

  • sort occurs

  • hiding and showing of divs happens at the last step

Initially, as I was not able to see any divs being shown/hide, I assumed that it was happening too fast for me to notice. So I added a time delay to the .show() and .hide() functions of jQuery. Once this was done, it was quite apparent that show and hide actions were being done at the very end.

* SOLUTION * After much searching, I managed to get this working as I expected by using jQuery .queue() and .dequeue() functions. The achilles heel here was that I had to insert a 1 millisecond delay between each operation. Then and only then was the browser able to hide/show divs as I wanted. So the operations went something like this:

    var theQueue = $({}); // jQuery on an empty object

theQueue.queue("testQueue",
                function( next) {
                    $("#loadingIndicator").show();
                    $("#cases").hide();
                    next();
                }
            );
theQueue.delay( 1, "testQueue" );

theQueue.queue("testQueue",
                function( next) {
                    doSort(columnNumber);  //SORT
                    next();
                }
            );
theQueue.delay( 1, "testQueue" );

theQueue.queue("testQueue",
                function( next) {
                    $("#loadingIndicator").hide();
                    $("#cases").show();
                    next();
                }
            );

theQueue.dequeue("testQueue");

}

I am certainly not an expert on the matter, but I would think that operations should be executing in the same order as they are called. Is the browser not rendering in the correct order? Is jQuery changing order of operations to make things more efficient?

While the "solution" does the job, I am not convinced that it is the best solution in this scenario. Is there any other way to do this? If needed, I can provide working code examples that will demonstrate the issue. Thank you.

On a different note, I have noticed with large data sets, when user clicks on a header element to trigger sort, browser become unresponsive. I realize it is executing the sort function, but I was hoping there would be a way to avoid this. Any thoughts?


The operations are being executed in the same order that they are called, but the problem is that the DOM elements and what's shown on the screen are two separate things. The process that renders the elements to the screen runs in the same single threaded environment as the Javascript code, so it can't show any changes on the sceen until your script finishes.

To get the changes to show up, you have to end your script, and then resume it once the renderer has had a chance to show the changes.

You can use the setTimeout method to return control to the browser, and get the rest of the code to start as soon as possible:

$("#loadingIndicator").show();
$("#cases").hide();

window.setTimeout(function(){

  doSort(columnNumber);  //SORT
  $("#loadingIndicator").hide();
  $("#cases").show();

}, 0);


.show() and .hide() are members of the fx queue, which is executed asynchronously, without halting program execution.

Effects may be queued sequentially by chaining, but other code will execute independently of fx queue execution. The way to get the order of operations the way you want is to create a custom queue like you did, or use the callback functions for each effect.

E.g.

$('#loadingIndicator').show(250,function(){
    $('#cases').hide(250,function(){
        doSort(columnNumber);
    }).show(250, function(){
        $('#loadingIndicator').hide(250);})
});

JSFiddle example

ED: I accidentally the whole word.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜