此代码随机播放音频元素。运行 setup
两次可以让您同时对两个不同的数组执行此操作,这就是我想要的。问题是 #stop
仅停止其中一个数组的播放。如果您只在一个数组上调用 setup
,但多次单击 #start
(我也不希望出现这种情况),实际上也会发生这种情况。我认为这与“intervalReturn”有关,因为它只能指定为一个 setInterval
。
我应该如何编写此代码,以便多次调用 setup
创建只能启动一次的不同 setIntervals?
或者,如果我应该从完全不同的 Angular 来处理这个问题,什么会更好?
编辑:此问题已根据以下建议修复。但我想知道,这里 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);
});
最佳答案
But I'm wondering, what is going on "under the hood" with setInterval here?
每次您调用 setup()
,这会在 #start
上创建额外点击处理程序和#stop
元素。当您实际单击#start
时,或#stop
,所有所有适用的处理程序都会被调用(按照它们绑定(bind)的顺序)。这就是为什么点击 #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()
后立即调用一这样它就会记录刚刚返回的间隔 ID,而不是前一个间隔 ID。这样您就可以看到所有相关变量的值并了解发生了什么。
关于javascript - 使用一个函数进行多个 setIntervals (Javascript),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44579911/