简体   繁体   English

函数执行顺序错误

[英]Functions executing in wrong order

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. 我有3个标签,默认情况下其中一个处于活动状态。 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. 现在,应在触发shown.bs.tab事件之前执行getQueueData()函数。 This is necessary for the latter event to be able to access the values in the queues object. 这对于后面的事件必须能够访问queues对象中的值是必需的。 In fact, however, when the page is loading, the shown.bs.tab function is executing first, followed by getQueueData(). 但是,实际上,在页面加载时,首先执行了shown.bs.tab函数,然后是getQueueData()。 This means that in the shown.bs.tab method, queues is undefined the first time. 这意味着在shown.bs.tab方法中,第一次未定义queues I know it because the HELLO WORLD and an empty object is printing in the log before the console.log(queues[str]) output. 我知道这是因为HELLO WORLD和一个空对象正在console.log(queues[str])输出之前的日志中打印。 Does anyone know how I can make the getQueueData() execute completely before going to the 'shown.bs.tab' event? 有谁知道在进入'shown.bs.tab'事件之前如何使getQueueData()完全执行?

Haha! 哈哈!

Pretty common question for beginners in javascript's asynchronous realm. 对于javascript异步领域的初学者来说,这是一个很常见的问题。 :) Welcome to the jungle mate. :)欢迎来到丛林伙伴。 ;) ;)

Here is the magic trick. 这是魔术。 Move your $('.nav a[href="#queue1"]').tab('show'); 移动您的$('.nav a[href="#queue1"]').tab('show'); inside $.post function. $.post函数中。 Put it after your for loop. 将其放在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.
        });
    }

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. 您所担心的是, getQueueData()应该在显示的shown.bs.tab之前执行。 However, it does appear that getQueueData() gets executed after your tabs show event. 但是,在选项卡显示事件之后,确实会执行getQueueData() Why is that? 这是为什么? Because you have an asynchronous call inside your getQueueData() . 因为您的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. 该脚本将对interface/getqueues.php进行API调用,并且由于它是异步的,因此它具有英勇的性质,并且它不会等到服务器做出响应。 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. 它继续执行,并从函数getQueueData()返回,然后继续并触发选项卡上的show事件(因为调用getQueueData之后的下一条语句是选项卡的show语句。

When the server responds, it will trigger the callback you have specified in your $.post function call. 服务器响应时,它将触发您在$.post函数调用中指定的回调。 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. 因此,当执行此回调时(在从服务器接收到响应之后,选项卡上的show事件已经发生。这就是为什么在选项卡show事件之后getQueueData似乎正在执行的原因。但是实际上,它已执行在标签显示事件之前,以及在需要时进行$.post回调。

For more information, please read this awesome guide . 有关更多信息,请阅读此出色的指南

post is an asynchronous method. post是一种异步方法。 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. Javascript是一种语言,它不会等待异步方法的结果继续执行其余代码。

Thus, you have to synchronizde your code by your own. 因此,您必须自己同步代码。

One thing that you can use for this purpose is deferred object . 您可以用于此目的的一件事是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 . 您可以等待函数使用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();

    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM