【问题标题】:Javascript: wait for function in loop to finish executing before next iterationJavascript:等待循环中的函数在下一次迭代之前完成执行
【发布时间】:2014-07-30 15:42:36
【问题描述】:
$(function() {
$("#submit").click(function() {


for (var i=1; i<=14; i++)
{
        setID(i); 
        checkField(i);

}

if ($('#pass_fail').val() != "fail")
{ 
//do something
}

当我单击注册表单的提交按钮时会发生这种情况。

我想要的执行顺序:


setID(1);
checkField(1); //等待这个完成
setID(2);
checkField(2);
setId(3);
checkField(3);
....
if 语句

我得到的执行顺序:


for 循环从 i=1 到 i=14
if 语句
checkField(i)s 随机排列

问题:$('#pass_fail').val() 的默认值为'pass'。但是,通过循环 checkField(i) 可能会将其值更改为“失败”。但由于实际上 if 语句是在 checkField(i)s 之前执行的,所以 $('#pass_fail') 的值总是以 'pass' 结束,而 'do something' 总是执行。

如何等待 checkField(i) 完成执行,然后再进行循环的下一次迭代?提前谢谢!

【问题讨论】:

  • 要将异步函数转换为同步函数,您可能需要重构 checkField 以回调下一个 checkField。
  • 那么,checkField() 执行服务器请求?为什么不一起抓取所有字段并一次检查它们?
  • 对,checkField() 包含一个 Ajax 调用,它访问一个带有检查不同字段的函数的 php 文件。我不能对所有字段执行一次调用的原因是因为每次调用都会返回一个不同的错误消息,对应于那个字段。如果单个 checkField() 一次检查所有字段,则所有不同字段的错误将显示在同一字段下。

标签: javascript jquery for-loop asynchronous callback


【解决方案1】:

根据您对问题的描述,我假设checkField() 正在进行某种异步 Ajax 调用。如果您真的想序列化对checkField() 的调用,那么在第一次调用完成之前不会进行第二次调用,那么您需要更改代码的结构和流程才能做到这一点。这样做的两种常见方法是使用回调来指示对 checkField() 的调用完成,从而触发对 checkField() 的下一次调用,或者使用 Promise 来完成类似的事情。

这里是回调机制的一个例子:

$("#submit").click(function() {
    var i = 0;
    function next() {
        i++;
        if (i <= 14) {
            setID(i);
            checkField(i, next);
        } else {
            // all checkField operations are done now
            if ($('#pass_fail').val() != "fail") { 
                //do something
            }
        }
    }
    next();
});

然后,checkField() 必须修改为在完成异步操作时调用传递给它的回调。


如果您使用 jQuery 在 checkField 中进行 ajax 操作,那么使用 jQuery Promise 也可以很容易地解决这个问题。

【讨论】:

    【解决方案2】:

    抱歉,但在较早的回复中,我没有看到任何循环等待任何其他函数或任何内部循环执行以使其在下一次迭代之前完成。

    使用 JQuery 3.3.1

    场景: for loopvar i 将在 i 的下一次迭代值之前等待内部其他循环完成

    $(document).ready(function(){
    
        $("p").click(function() {
        
        	var varIDeferred = $.Deferred();
            var varJDeferred = $.Deferred();
            
            /*
            var loopJInside = function(j) {  
                console.log("j is : " + j);
                $("span").html($("span").html() + "<br>j is : " + j);
                varJDeferred.resolve();
                j++;
                console.log("j value after incr is : " + j);
                return j;
            }
            
            // call inside loopJ
            setTimeOut(j = loopJInside(j), 500);
            */
            
            var loopJ = function(valueI) {
            
                for (var j = valueI; j < (3+valueI); ) {
            	    
            	varJDeferred = $.Deferred();
                    $("span").html($("span").html() + "<br>j is : " + j);
                    j++;
                    varJDeferred.resolve();
                    
                }
                
                varIDeferred.resolve();
                
                return (valueI+1);
            };
            
           	for(var i = 0; i < 3; ) {
           	    
           	    varIDeferred = $.Deferred();
           	    
    	    $("span").html($("span").html() + "<br>value of i is : " + i);
                
                if (i == 3)
                    break;
                	
                i = loopJ(i);
            };
            
        });
    });
    <!DOCTYPE html>
    <html>
    <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    </head>
    <body>
    
    <p style="cursor:default;border:2px solid black;width:60px;padding:5px;">Click me</p>
    <span><span>
    
    </body>
    </html>

    希望这对很多人有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-15
      • 2015-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-29
      • 2018-02-08
      • 1970-01-01
      相关资源
      最近更新 更多