Javascript 对于连续多次setTimeout调用未正确重复的循环?

Javascript 对于连续多次setTimeout调用未正确重复的循环?,javascript,jquery,Javascript,Jquery,长话短说,我在chrome开发者控制台中工作,我有一个javascript函数(我决定调用main进行说明),它可以进行4个函数调用,但4个函数调用中的每一个都需要间隔几秒钟,以允许页面正确更新,并允许用户对生成的对话框做出反应 当我在内部的4个函数调用中添加一个带有延迟的setTimeout并运行一次时,main函数工作得非常好。当我尝试将主函数循环X次时,它不起作用 通过阅读其他类似问题和文档,我可以了解到,这与setTimeout如何工作以及chrome浏览器中的javascript引擎如

长话短说,我在chrome开发者控制台中工作,我有一个javascript函数(我决定调用main进行说明),它可以进行4个函数调用,但4个函数调用中的每一个都需要间隔几秒钟,以允许页面正确更新,并允许用户对生成的对话框做出反应

当我在内部的4个函数调用中添加一个带有延迟的setTimeout并运行一次时,main函数工作得非常好。当我尝试将主函数循环X次时,它不起作用

通过阅读其他类似问题和文档,我可以了解到,这与setTimeout如何工作以及chrome浏览器中的javascript引擎如何是单线程的复杂性有关。。。还是什么?虽然不是我的专业知识,但我尝试过尽职调查,最终我不知道如何解决问题,甚至搜索其他问答和文档也无法找到有效的解决方案

我用setTimeout(,delay*I)方法和setTimeout(,delay)方法尝试了下面的代码,但是没有传入for循环的索引来乘以延迟,这两种方法都不能正常工作

其他问题建议使用嵌套设置超时,我不知道如何在这里实现?还有人建议使用setInterval,但我不确定如何在一定的时间内完成这一任务,因为我的每个调查都有一定数量的问题,我不希望主函数的重复次数超过调查中的最大问题量

for(let i = 1; i < 15+1; i++) {
    main(i);
}


function main(i){
    setTimeout(takescreenshot, 2000*i);
    setTimeout(checkforanswers,5000*i);    
    setTimeout(takescreenshot, 8000*i);
    setTimeout(function(){$("[name=next_question_button]")[0].click();},11000*i);

}
for(设i=1;i<15+1;i++){
主要(i);
}
主要功能(一){
设置超时(截图,2000*i);
设置超时(检查应答,5000*i);
设置超时(截图,8000*i);
setTimeout(函数(){$(“[name=next_question_button]”[0])。单击();},11000*i);
}
主函数应该每次循环任意次数,在我看来,程序流程应该是:

  • 在执行main延迟2秒后执行“takescreenshot”功能
  • 在调用main后5秒和在main中调用第一个函数后3秒执行“checkforanswers”函数。步骤1-2之间的间隙允许用户响应出现的打印对话框。 3.在调用main后8秒和上一步后3秒执行“takescreenshot”功能,允许页面DOM元素正确更新,以反映第一个屏幕截图的更改
  • 点击“next_question”(下一个问题)按钮进入调查中的下一个问题,在调用main后11秒,在最后一个屏幕截图后3秒进入下一个问题,允许对调查中的新问题重复4个步骤

  • 当执行一次时,它完全按照我所希望的那样工作,但是当循环多次时,步骤1-4开始出现,没有适当的延迟,并且在每个步骤中的相关“等待X”得到满足之前开始出现,并且所有这些都混合在一起,获得不可预测和不想要的结果。

    您的算法已关闭。您应该将
    i
    乘以完成整个迭代所需的时间,然后再加上2、5或8秒。例如,如果从一次迭代的
    takescreenshot
    到下一次迭代的
    takescreenshot
    所需时间为14000 ms,则使用:

    function main(i){
        setTimeout(takescreenshot, 2000 + (i * 14000));
        setTimeout(checkforanswers,5000 + (i * 14000));    
        setTimeout(takescreenshot, 8000 + (i * 14000));
        setTimeout(function(){$("[name=next_question_button]")[0].click();},11000 + (i * 14000));
    }
    
    如果您指定函数并在
    for
    循环中等待
    中的每个调用,则操作顺序会更清晰:

    (async () => {
      for (let i = 1; i < 15 + 1; i++) {
        await main();
      }
    })();
    
    
    function main() {
      setTimeout(takescreenshot, 2000);
      setTimeout(checkforanswers, 5000);
      setTimeout(takescreenshot, 8000);
      return new Promise((resolve) => {
        setTimeout(function() {
          $("[name=next_question_button]")[0].click();
          resolve();
        }, 11000);
      });
    }
    
    (异步()=>{
    for(设i=1;i<15+1;i++){
    等待main();
    }
    })();
    函数main(){
    设置超时(截图,2000年);
    设置超时(检查应答,5000);
    设置超时(截图,8000);
    返回新承诺((解决)=>{
    setTimeout(函数(){
    $(“[name=next\u question\u button]”[0]。单击();
    解决();
    }, 11000);
    });
    }
    
    如果
    i
    2
    设置超时(截图,2000*i)2000*2
    毫秒将被调用

    但您希望它在调用main后的几毫秒内被调用
    11000+2000
    。其他超时情况也是如此

    由于
    i
    1
    开头,您希望使用
    11000*(i-1)
    作为添加到每个超时函数的延迟

    function main(i){
        let delay = 11000 * (i - 1);
        setTimeout(takescreenshot, 2000 + delay );
        setTimeout(checkforanswers, 5000 + delay );    
        setTimeout(takescreenshot, 8000 + delay );
        setTimeout(function(){$("[name=next_question_button]")[0].click();}, 11000 + delay);
    
    }
    

    以下是经典的分块方法:

    function chunks([first, ...other], delay = 2000, result) {
      const nextResult = first(result);
      setTimeout(() => chunks(other, delay, nextResult), delay);
    }
    
    const simpleFunction = () => { return 'whatever'; };
    const functionWithParams = (a, b) => a + b;
    
    const pipe = [
      simpleFunction,
      () => functionWithParams(3, 5),
      data => console.log('inline code to run, which uses prev result (3+5=8): ' + data),
    ];
    
    chunks(pipe);
    // or chunks(pipe, 5000);
    

    for循环不等待,因此您只需对整个循环进行间隔毫秒的超时调用。因此,您基本上要调用
    takescreenshot
    15次。 只需使用main调用自己。在最后一次超时中,调用main以重复

    function main(i){
        setTimeout(takescreenshot, 2000*i);
        setTimeout(checkforanswers,5000*i);    
        setTimeout(takescreenshot, 8000*i);
        setTimeout(function(){
          $("[name=next_question_button]")[0].click();}
          if (i<14) {
            main(i+1)
          }
        }, 11000*i)
    }
    
    main(0)
    
    主功能(一){
    设置超时(截图,2000*i);
    设置超时(检查应答,5000*i);
    设置超时(截图,8000*i);
    setTimeout(函数(){
    $(“[name=next_question_button]”[0]。单击();}
    
    如果我的解决方案和上面提到的“t.niese”解决方案都能解决我的问题。实际上,我认为我正在实现一个类似于上面提出的“等待”解决方案的解决方案,在解决所有问题之前,主循环不会开始下一次迭代,但我最初实现了一个类似于“t.niese”的解决方案但我的算法不正确。感谢你们和其他评论者!