setTimeout中的多个任务未按预期工作

时间:2014-02-22 17:34:40

标签: javascript css closures settimeout

我之前问过一个关于在使用闭包的foreach中使用setTimeout的问题: Javascript setTimeout in foreach: need help creating a closure

选择的答案对我有用但是我现在有一个不同的问题。这是我想要做的:

playAllNotes(0);
function playAllNotes(index) {
    if(notes.length > index) {
        setTimeout(function() {
            $('mydiv').addClass('playing-note');
            playNote(notes[index]);
            $('mydiv').removeClass('playing-note');
            playAllNotes(index++);
        }, 1000);
    }
}

上面的代码(没有add和remove类)按预期工作 - 每秒播放一次音符。但是,我想要做的是在播放音符时也改变div的颜色,所以我在playNote()方法之前有addclass和removeclass。结果是笔记仍然可以正常运行,但是css更改不起作用 - 我认为正在发生的事情是添加和删除不会通过超时逻辑,因此在我注意到之前它被删除(因为它实际上在调试模式下工作)。

我想我不完全理解超时是如何工作的,所以如果有人能帮我解决上述代码,我会很感激。

更新: playNote()使用MIDI.js库播放钢琴音符:

function playNote(noteNumber){
  var velocity = 127;
  var delay = 0;
  var instrumentChannel= 0;  
  MIDI.noteOn(instrumentChannel, noteNumber, velocity, delay);  
}

3 个答案:

答案 0 :(得分:3)

您的问题与超时无关:它与渲染引擎行为有关。

HTML呈现是异步的:您添加playing-note类,但不会立即呈现。

但是,您的代码是同步的:您立即删除playing-note类,并在应用下一个渲染时......然后没有任何更改。

你需要的是增加另一个超时以延迟课程的移除,并给人眼注意时间,以便注意到这一变化。

例如:

playAllNotes(0);
function playAllNotes(index) {
    if(notes.length > index) {
        setTimeout(function() {
            $('mydiv').addClass('playing-note');
            playNote(notes[index]);
            // let say 250ms is enought for people to notice the change.
            setTimeout(function() {
                $('mydiv').removeClass('playing-note');
            }, 250);
            playAllNotes(index++);
        }, 1000);
    }
}

答案 1 :(得分:0)

你也可以试试这个:

 playAllNotes(0);
function playAllNotes(index) {
if(notes.length > index) {
    setTimeout(function() {
        $('mydiv').addClass('playing-note');

        playNote(notes[index],index);

    }, 1000);
}
}

  function playNote(noteNumber,index){
  var velocity = 127; 
 var delay = 0; var instrumentChannel= 0;
 MIDI.noteOn(instrumentChannel, noteNumber, velocity, delay);

 $('mydiv').removeClass('playing-note');
playAllNotes(index++);
 }

答案 2 :(得分:0)

另一种方法

playAllNotes(0);
function playAllNotes(index) {
    if(notes.length > index) {
        setTimeout(function() {

            $("mydiv").addClass("playing-note").delay(1000).queue(function(next){
                $(this).removeClass("playing-note");
                next();
            });

            playNote(notes[index]);
            playAllNotes(index++);
        }, 1000);
    }
}