函数执行顺序错误

时间:2015-08-21 08:56:21

标签: javascript jquery

我的问题有点难以解释,但我会尽我所能。我有3个选项卡,其中一个默认是活动的。每次激活选项卡时,都会触发一个事件。但是,标签标题是在之前设置的功能中设置的。我的代码如下:

<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>

现在,getQueueData()函数应该在shown.bs.tab事件被触发之前执行。这对于后一个事件能够访问queues对象中的值是必要的。实际上,当页面加载时,shown.bs.tab函数首先执行,然后是getQueueData()。这意味着在shown.bs.tab方法中,第一次queues未定义。我知道这是因为HELLO WORLD和一个空对象在console.log(queues[str])输出之前在日志中打印。有没有人知道如何在进入'shown.bs.tab'事件之前完全执行getQueueData()?

2 个答案:

答案 0 :(得分:4)

哈哈!

javascript异步领域初学者的常见问题。 :) 欢迎来到丛林伴侣。 ;)

这是魔术。移动$('.nav a[href="#queue1"]').tab('show');内部$.post功能。将它放在for循环之后。 :)

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.
        });
    }

一切都会很好。

很快就会以解释的方式更新这个答案。 :)

==

编辑:

解释

getQueueData()应该在shown.bs.tab之前执行的问题已经完成。但是,在标签显示事件后,似乎会getQueueData()执行。 这是为什么? 因为您在getQueueData()内有异步调用。该脚本将对interface/getqueues.php进行API调用,因为它是异步的,它的英雄性质会接管,它不会等到服务器响应。它继续执行并从函数getQueueData()返回并继续并触发选项卡上的show事件(因为调用getQueueData后的下一个语句是标签的show语句。

当服务器响应时,它将触发您在$.post函数调用中指定的回调。 因此,当执行此回调时(从服务器收到响应后,选项卡上的show事件已经发生)。 这就是为什么在标签显示事件后getQueueData似乎正在执行的原因。 但实际上,它会在标签显示事件之前执行,并且只要有必要就会发生$.post的回叫。

有关详情,请参阅此awesome guide

答案 1 :(得分:2)

post是一种异步方法。这意味着它的结果不一定在调用之后得到。 Javascript是这样的语言,它不会等待异步方法的结果继续执行其余的代码。

因此,您必须自己同步代码。

您可以用于此目的的一件事是deferred object。创建它时,它具有挂起状态。无论何时解决或拒绝该对象,您都会收到通知。

下面,请注意如何使用它。

  • 您可以等待使用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();

    });
}