Javascript 在循环中设置超时,在前一个函数完成后执行3个函数

Javascript 在循环中设置超时,在前一个函数完成后执行3个函数,javascript,jquery,loops,settimeout,deferred,Javascript,Jquery,Loops,Settimeout,Deferred,I 3个函数a、b和c将在循环中执行x次,如下所示: 我必须调用函数a;a完成后,我必须等待s1秒才能调用函数b;s1秒过后,我必须调用函数b;b完成后,我必须等待2秒才能重新启动循环 for(var i=0; i<x; i++) { a(); setTimeout(b,s1); setTimeout(function() {},s2); } 然而,在上述循环中,函数a和b不能正确执行。无论上一个函数是否已完成,都会执行它们 我还尝试了: var FunctionOne = functi

I 3个函数a、b和c将在循环中执行x次,如下所示: 我必须调用函数a;a完成后,我必须等待s1秒才能调用函数b;s1秒过后,我必须调用函数b;b完成后,我必须等待2秒才能重新启动循环

for(var i=0; i<x; i++) {
a();
setTimeout(b,s1);
setTimeout(function() {},s2);
}
然而,在上述循环中,函数a和b不能正确执行。无论上一个函数是否已完成,都会执行它们

我还尝试了:

var FunctionOne = function () {
// create a deferred object
var r = $.Deferred();

// do whatever you want (e.g. ajax/animations other asyc tasks)
a();

setTimeout(function () {
    // and call `resolve` on the deferred object, once you're done
    r.resolve();
}, s1);

// return the deferred object
return r;
};

var FunctionTwo = function () {
    b();
};

for(var i=0; i<x; i++) {
setTimeout(FunctionOne().done(FunctionTwo),s2);
}
但它并没有达到预期的效果

你能帮我吗

编辑

职能a和b如下:

function a() {
$.ajax({
        type: $('#form1').attr('method'),
        url: 'Misura',
        data: $('#form1').serialize(),
        beforeSend: function() {
            if($.trim($('#nomeMisura').val()) == "") {
                alert('<%= labels.getString("nomeMisuraObbligatorio") %>');
            $('#nomeMisura').val("");
            return false;
        }
    },
    success: function (data) {
        $('#misura').attr('disabled', true);
        $('#pulisci').attr('disabled', false);

        misurazioneInCorso = true;
    }
});
}

}


因此,我认为a和b是异步函数。

您可以实现某种调度器:下面我使用一个最简单的堆栈,其中包含函数或下一个任务执行前的等待时间。 下面的代码未经测试,但可能会给您一些想法:

var tasks =  [];         // list of all tasks / wait time
var currTaskIndex = 0;  
var looping = true;

function runTask() {
   if (currTaskIndex==-1) return;
   var currTask = tasks[currTaskIndex];
   // iterate
   currTaskIndex++;
   if (currTaskIndex==tasks.length) {
        if(looping ) {
           currTaskIndex=0;
         } else {
           currTaskIndex=-1;               
         }
   }
   // run task / wait
   if (typeof currTask == "function") {
      currTask.call(null);
      runTask();
   } else {
     // currTask is a time -> wait
     setTimeout(runTask, currTask);
   }
}
配合使用

tasks.push(a);
tasks.push(s1);
tasks.push(b);
tasks.push(s2);

runTask();

对于异步调用,始终需要将下一步(取决于异步活动的结果)放入异步活动结束时调用的回调方法中

根据您的评论,您的方法包含异步ajax调用。setTimeout调用也是异步的。如果你打电话:

setTimeout(b,s1);
setTimeout(c,s2);
然后两个超时将同时运行。这意味着你正在进入地狱的世界……这并不像有些人想象的那么难,但这是一种不同的思维方式

为了防止后续方法执行,并防止循环仅仅进入下一个迭代并同时执行整个循环,您需要在a的末尾调用b,在b的末尾调用c。在开始下一次迭代之前,您还必须等待c的结束,这意味着在c完成后循环,而不是将c放入循环中……否则,您的循环将立即通过所有x次迭代,并且您将让所有方法几乎同时运行,除了a,因为它是一个同步调用,考虑到我之前提到的假设。因此,您需要做的是:

var i = 0;
var x = 100;

function a() {
    //end our loop inside the method
    if( i++ < x ) {
        //shortening your ajax call to just success method
        var ajaxSuccess = function (data) {
            $('#misura').attr('disabled', true);
            $('#pulisci').attr('disabled', false);

            misurazioneInCorso = true;

            setTimeout(b,s1);
        }
    }
}
function b() {
    //shortening your ajax call to just success method
    var ajaxSuccess = function (data) {
        var numeroCampioniMisurazione = Number(data.delta.campione2) - Number(data.delta.campione);
        //visualizzo in tabella le misurazioni
        $('#tabellaMisurazioni').append('<tr id="Misurazione"><td>'+data.nomeSessione+'</td><td>'+data.nome+'</td><td>'+data.delta.campione+'</td><td>'+data.delta.campione2+'</td><td>'+numeroCampioniMisurazione+'</td><td>'+data.delta.f1+'</td><td>'+data.delta.f2+'</td><td>'+data.delta.f3+'</td><td>'+data.delta.f4+'</td><td>'+data.delta.f5+'</td><td>'+data.delta.f6+'</td><td>'+data.delta.f7+'</td><td>'+data.delta.f8+'</td><td>'+data.delta.f9+'</td><td>'+data.delta.f10+'</td><td>'+data.delta.f11+'</td><td>'+data.delta.f12+'</td><td>'+data.delta.t1+'</td><td>'+data.delta.t2+'</td><td>'+data.delta.to+'</td><td>'+data.delta.ft+'</td><td>'+data.delta.rh+'</td></tr>');
        $('#tabellaMisurazioni tbody tr:first').html('<td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td><td>---</td>');

        $('#misura').attr('disabled', false);
        $('#pulisci').attr('disabled', true);
        $('#esportaCsvMisurazioni').attr('disabled', false);
        $('#nomeMisura').val('');

        misurazioneInCorso = false;

        setTimeout(c,s2);
    }
}
function c() {
    //do your stuff, then loop back to a
    a();
}

a();

注意,我正在做的唯一一件事是将下一个调用放入AJAX调用的success方法中,我通过使用c调用a而不是将其放入for循环来循环。然后,我修改了a,这样它将在x次迭代后结束循环,而不在if中执行。这将确保它们按顺序运行。

我建议的代码与Kevin Nelson的代码非常相似。在我的代码中,控制逻辑不包括在应用程序函数中

var x=5;
outerFun(){
    if(x){
        a();
        setimeout(function(){
            b();
            setTimeout(function(){
                //do its part
                x--;
                outerFun();
            },s2);      
        },s1);
    }
}
您可以在以下链接中找到我的解决方案的PDF版本-其中包括分析,代码可能在末尾找到:

以下是从PDF文档生成的


在第二种方法中,有什么不起作用?是同步的还是异步的?我用a和b函数编辑了我的第一篇文章。它们似乎是异步函数$.ajax调用。我还没有时间尝试任何提议的解决方案。我不知道哪一个适合异步函数。已更新为使用来自ajax调用的回调。我不确定此解决方案是否能按我的要求工作,因为a和b函数包含异步ajax调用。例如,在函数PL1中,我需要a在调用setTimeoutPL2、s1之前完成其所有任务。我不知道为什么,但您的解决方案似乎有效:非常感谢!
var x=5;
outerFun(){
    if(x){
        a();
        setimeout(function(){
            b();
            setTimeout(function(){
                //do its part
                x--;
                outerFun();
            },s2);      
        },s1);
    }
}