2

My problem is a bit hard to explain, but I'll try my best. I have 3 tabs, one of which is active by default. Every time a tab is activated, an event fires. However, the tab headings are set in a function set earlier. My code is given below:

<script>
    var queues = {};

    $(document).ready(function(){

        getQueueData();
        $('.nav a[href="#queue1"]').tab('show');
    });

    function getQueueData(){

        $.post('interface/getqueues.php', function(data){


            var str = "#q";
            for (var i=0; i<data.data.length; i++){
                str += i;
                $(str).text(data.data[i]["name"]);
                queues[str] = data.data[i];
                console.log(queues[str]);
                str = "#q";   
            }
        });
    }

    $('a[data-toggle="tab"]').on("shown.bs.tab", function(event){
        console.log("HELLO WORLD!");
        var elem = $(this).attr("id");
        var id = "#"+elem;
        console.log(queues);
    });


</script>

Now, the getQueueData() function should execute BEFORE the shown.bs.tab event is fired. This is necessary for the latter event to be able to access the values in the queues object. In fact, however, when the page is loading, the shown.bs.tab function is executing first, followed by getQueueData(). This means that in the shown.bs.tab method, queues is undefined the first time. I know it because the HELLO WORLD and an empty object is printing in the log before the console.log(queues[str]) output. Does anyone know how I can make the getQueueData() execute completely before going to the 'shown.bs.tab' event?

3
  • 1
    It sounds like you need to use a promise. Check out this: stackoverflow.com/questions/20122227/… Commented Aug 21, 2015 at 8:59
  • I believe you need to fire the shown.bs.tab event after you finish the async post, so call it at the end of the $.posts callback function. Commented Aug 21, 2015 at 9:00
  • 1
    Or just simply wrap your $('a').on('shown.bs.tab') in a function wrapper and call it from the successful post callback. Commented Aug 21, 2015 at 9:00

2 Answers 2

4

Haha!

Pretty common question for beginners in javascript's asynchronous realm. :) Welcome to the jungle mate. ;)

Here is the magic trick. Move your $('.nav a[href="#queue1"]').tab('show'); inside $.post function. Put it after your for loop. :)

function getQueueData(){

        $.post('interface/getqueues.php', function(data){


            var str = "#q";
            for (var i=0; i<data.data.length; i++){
                str += i;
                $(str).text(data.data[i]["name"]);
                queues[str] = data.data[i];
                console.log(queues[str]);
                str = "#q";   
            }
            $('.nav a[href="#queue1"]').tab('show'); // << Triggre your show event here.
        });
    }

And everything will work great.

Will be updating this answer with explanation, soon. :)

==

EDIT:

Explanation.

Your concern, that getQueueData() should execute BEFORE shown.bs.tab is already fulfilled. However, it does appear that getQueueData() gets executed after your tabs show event. Why is that? Because you have an asynchronous call inside your getQueueData(). The script will make an API call to interface/getqueues.php and because it is asynchronous, it's heroic nature takes over and it doesn't wait until the server responds. It continues it's execution and returns from function getQueueData() and goes ahead and triggers the show event on your tabs (because the next statement after a call to getQueueData is your tabs's show statement.

When the server responds, it will trigger the callback you have specified in your $.post function call. Therefore when this callback executes (which is after response is received from the server, the show event on your tabs has already taken place. And this is why it seems like getQueueData is getting executed after tabs show event. But in reality, it is executed before the tabs show event and the call back of $.post happens whenever it's necessary.

For more information, please read this awesome guide.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you, it worked! I am still trying to fully understand these asynchronous operations.
Once I did put it in the getQueueData() method, but after the $.post function. It was showing undefined.
@user3033194: Check the updated answer, let me know in case of any questions.
I see, so the call order is - first getQueueData() in which an asynchronous call is made, then the tabs function, then back to the callback function code for $.post in getQueueData() (when the async call is completed). Is this right?
OK, I got it now. Thank you for the explanation.
|
2

post is an asynchronous method. It means that its result is not necessarily get just after it is called. Javascript is such language that it won't wait for the result of an async method to continue to execute the rest of code.

Thus, you have to synchronizde your code by your own.

One thing that you can use for this purpose is deferred object. When you create it, it has a pending state. Whenever you resolve or reject over that object, you will get notified.

Below, notice how you could use it.

  • You can wait for a function to be finished with a deferred object.

.

<script>
var queues = {};

var deferred = $.Deferred();

$(document).ready(function(){

    getQueueData();
    deferred.then(function() {
        $('.nav a[href="#queue1"]').tab('show');
    });

});

function getQueueData(){

    $.post('interface/getqueues.php', function(data){


        var str = "#q";
        for (var i=0; i<data.data.length; i++){
            str += i;
            $(str).text(data.data[i]["name"]);
            queues[str] = data.data[i];
            console.log(queues[str]);
            str = "#q";   
        }

        deferred.resolve();

    });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.