此代码随机播放音频元素。运行setup
两次允许您同时使用两个不同的阵列,这就是我想要的。问题是#stop
只停止其中一个阵列播放。如果您只在一个阵列上调用setup
,但多次点击#start
(我也不想要),也会发生这种情况。我认为这与'intervalReturn'有关,因为它只会指定给一个setInterval
。
我该怎么写这个,以便setup
的多次调用创建不同的setIntervals,只能启动一次?
或者,如果我从一个完全不同的角度来看待这个问题,那会更好吗?
编辑:这是根据以下建议修复的。但是我想知道,setInterval在“引擎盖下”发生了什么?为什么会发生这种行为? (具体来说:#stop
会停止一个但不是所有音频元素。)
var CMajor3 = new Array ("C3","D3","E3","F3","G3","A3","B3","C4a");
var CMajor4 = new Array ("C4b","D4","E4","F4","G4","A4","B4","C5");
var intervalReturn = null;
function pickAndPlay(pitchSet){
fyshuffle (pitchSet); // the Fischer-Yates shuffle function
var tone = document.getElementById(pitchSet[0]);
tone.currentTime = 0;
tone.play();
};
function setup(time, pitchSet){
$("#start").click(function() {
console.log("startClicked");
intervalReturn = window.setInterval(pickAndPlay, time, pitchSet)
});
$("#stop").click(function() {
console.log("stopClicked");
window.clearInterval(intervalReturn)
});
};
$(document).ready(function() {
setup(2000, CMajor3);
setup(2000, CMajor4);
});
答案 0 :(得分:1)
但我想知道,发生了什么事情"引擎盖下"在这里使用setInterval?
每次拨打setup()
时,都会在#start
和#stop
元素上创建其他点击处理程序。当您实际点击#start
或#stop
时,会调用适用处理程序的所有(按照绑定的顺序)。这就是为什么点击#start
会导致CMajor3
和 CMajor4
注释发挥作用的原因。您将获得多个并发但不相关的间隔。
将intervalReturn
定义为全局变量,您只有从最近一次调用setInterval()
返回的间隔ID,因为每次#start
点击处理程序运行它覆盖前一个。这就是为什么点击#stop
只会停止其中一个间隔,而无法阻止其他间隔。
在var intervalReturn
函数中移动setup()
声明会有所帮助,因为closures work in JS的参数和局部变量setup()
的方式,即time
, pitchSet
和intervalReturn
(在您移动声明之后)可以在当前调用setup()
中定义的两个事件处理程序中访问。对setup()
的后续调用会创建具有这些变量的单独副本的新闭包。因此,#stop
点击处理程序会使用与其intervalReturn
相关的个人setup()
。由于两个#stop
处理程序都运行,因此两个间隔都会被清除。
但是,您仍然遇到以下问题:在不点击#start#
的情况下多次点击#stop
会创建额外的时间间隔,然后在任何setup()
个内intervalReturn
覆盖个人#stop
最新的,所以再次if (intervalReturn === null)
无法回顾之前的时间间隔。这就是为什么在#start
处理程序中添加intervalReturn = null
有助于仅在没有运行时启动新间隔的原因。 (然后您需要在#stop
处理程序中添加clearInterval(intervalReturn)
,因为只是调用intervalReturn
并不会更改console.log()
变量的值。)
建议:将现有的console.log("startClicked", pitchSet, intervalReturn);
// and
console.log("stopClicked", pitchSet, intervalReturn);
语句更新为以下内容:
startClicked
在调用setInterval()
之后可能会更多.
v 68.915850808760979 eval {set sim_annotation {1 received {how are you}}}
.
v 68.915850808760979 eval {set sim_annotation {question: how are you. answer: fine}}
.
v 70.508104551724557 eval {set sim_annotation {0 received {hi}}}
.
v 70.508104551724557 eval {set sim_annotation {question: hi. answer: Thanks}}
,以便它记录刚刚返回的间隔ID,而不是之前的。这样你就可以看到所有相关变量的值,看看发生了什么。