在它们之间执行延迟操作

时间:2017-06-14 15:20:43

标签: javascript asynchronous synchronization

我有一个我想要一个接一个地执行的动作列表。 假设我们有一个拳击袋锻炼:

发出哔哔声,然后2秒钟后教练告诉运动员该做什么('FOOTWORK')。 15秒后,教练告诉运动员改变他正在做的事情('TECHNIQUE')......这一直持续到一分钟过去了。然后,教练重复这个程序3次。

我正在尝试构建一个完全正确的库,但我遇到了每个操作之间的延迟问题。以下是我到目前为止所做的事情:

class Action{
    constructor(name = "Action", actualAction){
        this.name = name;
        this.actualAction = actualAction;
    }

    run(){
        console.log("Executing Action: " + this.name);
        this.actualAction();
    }
}

function repeat(times){
    var timesLeft = times;
    return function(){
        timesLeft--;
        return timesLeft > 0;
    }
}

class SleepAction extends Action{
    constructor(ms, nextAction){
        super("Sleep " + ms);
        this.ms = ms;
        this.nextAction = nextAction;
    }

    run(){
        setTimeout(this.nextAction.run(), this.ms);
    }
}

class Block extends Action{
    constructor(name = "Block", actions, repeat){
        super(name);
        this.repeat = repeat;
        this.instructions = actions;
    }

    run(){
        this.instructions.forEach(function(action) {
            action.run();
        });

        if(this.repeat()){
            this.run();
        }
    }
}

您可以告诉我正在使用 setTimeout 尝试使其正常工作,但在此示例中所有操作都会同时运行:

var doNothing = new Action("Nothing", function(){});

var boxingBagPreset = new Block("Boxing Bag 15-15-15-15 3 Times", 
        [beepAction, 
        new SleepAction(2000, new Block("Tiny Pause", [
            new Action("FOOTWORK", textToSpeech("FOOTWORK")),
            new SleepAction(15000, new Block("Sleep 15", [
                new Action("SPEED", textToSpeech("SPEED")),
                new SleepAction(15000, new Block("Sleep 15", [
                    new Action("POWER", textToSpeech("POWER")),
                    new SleepAction(15000, new Block("Sleep 15", [
                        new Action("REST", textToSpeech("REST")),
                        new SleepAction(15000, new Block("Sleep 15", [doNothing], repeat(1)))
                    ], repeat(1)))
                ], repeat(1)))
            ] , repeat(1)))
        ], repeat(1)))],
    repeat(3));

为了实现这一目标,我需要更改什么?

1 个答案:

答案 0 :(得分:2)

问题是你是在立即调用函数并传递结果而不是将函数本身传递给setTimeout

试试这个:



class SleepAction extends Action{
    constructor(ms, nextAction){
        super("Sleep " + ms);
        this.ms = ms;
        this.nextAction = nextAction;
    }

    run(){
        var func = () => this.nextAction.run();
        setTimeout(func, this.ms);
    }
}




由于处理this的方式,您无法通过this.nextAction.run,因为当this调用setTimeout时,this会有所不同。

在这个例子中,我创建了一个新函数来捕获ARSCNView