强制JavaScript按所需顺序执行

Forcing JavaScript to execute in desired order

本文关键字:顺序 执行 JavaScript 强制      更新时间:2023-09-26

我在尝试让Javascript按我想要的顺序执行函数时遇到了问题。我正试图获得一个jQuery模态表单来加载基于特定选择的信息。我有两个SELECT框需要加载,但第二个SELECT框的内容完全取决于第一个SELECT框所选的值。

我做了以下功能来请求我需要的信息:

function get_Subjects(varID, callback){
    $.post("../vars/get_SID.php", { vid : varID },  
        function(result){
            getInfo('tbsubjectdiv', '../vars/findSubjectlist.php?sid='+result);
        });
    callback();
}
function get_Selectedfields(varID, callback){
    $.post("../vars/requestTblock.php", { vid : varID },  
        function(result){
            populateForm('tbWiz', result);
            document.form_tbWiz.varname.disabled = true;
            $('.trSearch').hide();
            $('.trValueset').hide();
        });
    callback();
}
function get_TextblockType(varID, callback){
    $.post("../vars/requestVtype.php", { vid : varID },  
        function(result){
            if(result == 0){ //Opzoeken
                $('.trSearch').show();
            }else if(result == 1){ //Datum vergelijken
                $('.trSearch').show();
                $('.trValueset').show();
            }else if(result == 2){ //Percentage
                //
            }
        });
    callback();
}
  1. 第一个函数检查MySQL数据库中的选定值的第一个SELECT字段,并将结果加载到第二个SELECT字段。

  2. 第二个函数请求表单数据的其余部分,并使用populateForm()填充表单。它还隐藏我表格的某些部分是为功能三做准备的。

  3. 第三个函数基本上要求显示表单的哪些部分,因为这并不总是相同的。

这背后的全部想法是,我想使用populateForm()来填充所有表单字段。为了使populateForm()正确设置所选的SELECT选项,特定的SELECT字段必须首先包含它需要选择的option。有道理。我试着用我的第一个函数来确保这一点,它将加载所有的OPTION。然后我尝试使用get_Selectedfields()来填充所有正确的值。但事实并非如此。无论我尝试做什么,第一个函数中的getInfo()总是被调用为LAST。这使得populateForm()无法选择正确的选项,这让我抓狂。

我试图通过这样做来"强制"执行命令:

function getTextblock(var_ID){
get_Subjects(var_ID, function() {
    get_Selectedfields(var_ID, function() {
        get_Textblocktype(var_ID, function() {
            // Done
        });
    });
}); 

}

当我意识到它仍然没有按照我想要的方式工作时,我决定使用Chrome的开发工具来检查一切执行的顺序。这一切都如预期的那样工作,但在最后它直接跳回到getInfo(),这是我调用的FIRST函数的一部分。我完全不知道为什么getInfo()最后被执行。如果这只是在一开始就执行,在我希望它执行的地方,一切都会很好。

您必须在post请求的回调函数中调用回调:

function get_Subjects(varID, callback){
    $.post("../vars/get_SID.php", { vid : varID },  
        function(result){
            getInfo('tbsubjectdiv', '../vars/findSubjectlist.php?sid='+result);      
            callback();
        });
}
function get_Selectedfields(varID, callback){
    $.post("../vars/requestTblock.php", { vid : varID },  
        function(result){
            populateForm('tbWiz', result);
            document.form_tbWiz.varname.disabled = true;
            $('.trSearch').hide();
            $('.trValueset').hide();
            callback();
        });
}
function get_TextblockType(varID, callback){
    $.post("../vars/requestVtype.php", { vid : varID },  
        function(result){
            if(result == 0){ //Opzoeken
                $('.trSearch').show();
            }else if(result == 1){ //Datum vergelijken
                $('.trSearch').show();
                $('.trValueset').show();
            }else if(result == 2){ //Percentage
                //
            }
            callback();
        });
}

POST在您的函数中是异步处理的,因此您的"回调"实际上几乎是在您的初始调用之后立即执行的,而$.post的回调是在POST发生之后执行的。这能帮你解决问题吗?您可能需要在$.post("../vars/get_SID.php", { vid : varID }... 的回调中启动其余过程

$.post$.ajax的简写,因此您可以在jQuery文档中阅读更多内容,但我不建议切换到同步请求。如果您必须在执行下一个请求之前完成一个请求,那么从回调中启动下一步就是方法。

您使用的是ajax。第一个a表示异步。如果您从函数(结果)块调用函数,那么它们将按顺序出现。

或者(这不是一个好主意,但你可以做到)使用$.ajax()对象并将async设置为false。

由于您不知道ajax请求实际需要多长时间,因此只能在ajax响应中链接事件:

function getTextblock(var_ID){
    $.post(YOUR_TARGET, YOUR_DATA, function(result){
        YOUR_CODE
        // CHAIN HERE, call new function or sub ajax request
    });
}

韦斯利,

javascript将始终按照预定义的顺序执行。如果你在代码中间放了一堆"alerts()",你就可以尝到它的味道。

但对于回调来说,情况并非如此,因为它们将被移动到javascript执行堆栈的底部,在那里我们无法确定顺序,因为它们是由AJAX返回调用的,根据定义,AJAX返回是异步的。

即使ajax在一毫秒内执行,回调也不会执行,直到脚本块中的所有方法都完成。

实际上你有三个选择:

  1. 在回调中链接所有方法序列。请不要回叫应该是你,但"系统"会调用这些
//您首先需要的数据函数myStartPoint(){$.post(url,函数(结果){//对这个结果执行您需要的操作(这是您的回调,但是匿名的)//然后,调用下一步secondPoint();});}函数secondPoint(){$.post(url,函数(结果){//同样,回调是匿名的。。。您几乎不需要声明名为callback的东西//链上你需要的点数nextPoint();}}
  1. "强制"ajax与async:false选项同步。这可能会导致性能问题
  2. 最丑陋的是使用该死的setTimeout,这是非常非常错误的,但在您的情况下会起作用,因为即使在那些预期很快的回调之后,setTimeout也会将方法放在执行堆栈的底部。说真的,我之所以选择这个选项,是因为最终会有人说……不要走这条路