Javascript 按顺序运行不同的设置超时

Javascript 按顺序运行不同的设置超时,javascript,asynchronous,foreach,settimeout,Javascript,Asynchronous,Foreach,Settimeout,我有一系列不同的“分钟数”,我想一个接一个地倒计时: const steps = [{ label: "Label1", time: 4 }, { label: "Label2", time: 2 }, { label: "Label3", time: 1 } ]; function countdownTimer(time) { setTimeout(function () { console.log("DON

我有一系列不同的“分钟数”,我想一个接一个地倒计时:

const steps = [{
    label: "Label1",
    time: 4
  },
  {
    label: "Label2",
    time: 2
  },
  {
    label: "Label3",
    time: 1
  }
];

function countdownTimer(time) {

  setTimeout(function () {

    console.log("DONE");

  }, parseInt(time + "000"));
}

function start() {

  steps.forEach(function (step) {
    countdownTimer(step.time);
  });

}
但是,与setTimeout的性质一样,它们似乎都在同时运行,最短时间显示在第一位

如何使setTimeout按顺序运行它们,即显示4、2和1

这是代码笔:


完成后,您可以让计时器调用函数,并为下一个索引传递一个参数:

const steps=[{label:“Label1”,时间:4},{label:“Label2”,时间:2},{label:“Label3”,时间:1}];
功能倒计时(i){
如果(i>=steps.length)返回
setTimeout(函数(){
log(“完成”,步骤[i].label);
倒计时(i+1)
},步骤[i]。时间*1000);
}

倒计时(0)
您可以让计时器在完成后调用函数,并为下一个索引传递一个参数:

const steps=[{label:“Label1”,时间:4},{label:“Label2”,时间:2},{label:“Label3”,时间:1}];
功能倒计时(i){
如果(i>=steps.length)返回
setTimeout(函数(){
log(“完成”,步骤[i].label);
倒计时(i+1)
},步骤[i]。时间*1000);
}

倒计时(0)
这是一种方法

const output=document.getElementById(“结果”);
常数步长=[
{
标签:“标签1”,
时间:1
},
{
标签:“Label2”,
时间:2
},
{
标签:“Label3”,
时间:3
}
];
const processStep=(步骤)=>{
返回新承诺((解决、拒绝)=>{
如果(!步骤){resolve(false);}
让timeout=parseInt(step.time+“000”);
setTimeout(()=>{
日志(“完成”,超时);
output.innerHTML=“步骤”+Step.label+”在“+Step.time+”秒”之后完成;
解决(步骤);
},超时);
});
};
const processSteps=(步骤)=>{
设currentStep=steps.shift();
如果(!currentStep){return;}
日志(“处理步骤”,当前步骤);
processStep(当前步骤)。然后(()=>{
处理步骤(步骤);
});
};
处理步骤(步骤)

这是一种方法

const output=document.getElementById(“结果”);
常数步长=[
{
标签:“标签1”,
时间:1
},
{
标签:“Label2”,
时间:2
},
{
标签:“Label3”,
时间:3
}
];
const processStep=(步骤)=>{
返回新承诺((解决、拒绝)=>{
如果(!步骤){resolve(false);}
让timeout=parseInt(step.time+“000”);
setTimeout(()=>{
日志(“完成”,超时);
output.innerHTML=“步骤”+Step.label+”在“+Step.time+”秒”之后完成;
解决(步骤);
},超时);
});
};
const processSteps=(步骤)=>{
设currentStep=steps.shift();
如果(!currentStep){return;}
日志(“处理步骤”,当前步骤);
processStep(当前步骤)。然后(()=>{
处理步骤(步骤);
});
};
处理步骤(步骤)

您的函数应该等待倒计时结束,然后再启动另一个计时器,因此
forEach
将无法工作
forEach
仅当您将上一个对象的时间添加到当前计时器时才起作用,这似乎有点太多了。只需等待每个计时器完成,然后启动下一个计时器。使用回调函数:

function countdownTimer(obj, callback) {
    setTimeout(function(){ 
        console.log(obj.label + ": DONE");
        callback();                                   // when the current cound down is done call callback to start the next one
    }, parseInt(obj.time + "000"));
}

var start = (function () {                            // wrapping in an IIFE to not pollute the global scope with the index variable. You can get rid of it if you want
    var index = 0;                                    // since we are not using a regular loop nor forEach, we need an index to keep track of the current step
    return function next() {                          // this function is called for each step
        if(index < steps.length) {                    // it check if there still a step in the array steps
            countdownTimer(steps[index], next);       // if so it starts its count down timer, telling it to call next once it finished
            index++;
        }
    };
})();
函数倒计时(obj,回调){
setTimeout(函数(){
console.log(obj.label+“:DONE”);
callback();//当当前会话结束时,调用callback启动下一个会话
},parseInt(obj.time+“000”);
}
var start=(函数(){//包装在IIFE中,以避免索引变量污染全局范围。如果需要,可以将其删除
var index=0;//因为我们不使用常规循环或forEach,所以需要一个索引来跟踪当前步骤
返回函数next(){//每个步骤都调用此函数
if(index
示例:

const steps=[{label:“Label1”,时间:4},{label:“Label2”,时间:2},{label:“Label3”,时间:1}];
函数倒计时(obj,回调){
setTimeout(函数(){
console.log(obj.label+“:DONE”);
回调();
},parseInt(obj.time+“000”);
}
var start=(函数(){
var指数=0;
返回函数next(){
if(索引<步长长度){
倒计时(步骤[索引],下一步);
索引++;
}
};
})();
console.log(“启动…”);

start()您的函数应该等待倒计时结束,然后再启动另一个计时器,因此
forEach
将无法工作
forEach
仅当您将上一个对象的时间添加到当前计时器时才起作用,这似乎有点太多了。只需等待每个计时器完成,然后启动下一个计时器。使用回调函数:

function countdownTimer(obj, callback) {
    setTimeout(function(){ 
        console.log(obj.label + ": DONE");
        callback();                                   // when the current cound down is done call callback to start the next one
    }, parseInt(obj.time + "000"));
}

var start = (function () {                            // wrapping in an IIFE to not pollute the global scope with the index variable. You can get rid of it if you want
    var index = 0;                                    // since we are not using a regular loop nor forEach, we need an index to keep track of the current step
    return function next() {                          // this function is called for each step
        if(index < steps.length) {                    // it check if there still a step in the array steps
            countdownTimer(steps[index], next);       // if so it starts its count down timer, telling it to call next once it finished
            index++;
        }
    };
})();
函数倒计时(obj,回调){
setTimeout(函数(){
console.log(obj.label+“:DONE”);
callback();//当当前会话结束时,调用callback启动下一个会话
},parseInt(obj.time+“000”);
}
var start=(函数(){//包装在IIFE中,以避免索引变量污染全局范围。如果需要,可以将其删除
var index=0;//因为我们不使用常规循环或forEach,所以需要一个索引来跟踪当前步骤
返回f