为什么在Javascript中在循环中调用setTimeout要求这么高?
TLDR: 在Chrome OSX中运行以下JS代码时:为什么在Javascript中在循环中调用setTimeout要求这么高?,javascript,Javascript,TLDR: 在Chrome OSX中运行以下JS代码时: for (let i = 0; i < 4000; i++) { setTimeout(function () { }, i)} 我收到一条警告,说[违规]“点击”处理程序耗时265毫秒。 为什么呢 背景: 我正在开发一个与音乐相关的应用程序,我们希望实现的功能之一是能够在循环中播放1000倍于1000倍的度量值,在用户体验方面类似于“无限”。如果一个度量值有4个注释,则需要设置1000*4个超时,这导致了这个巨大的性能问
for (let i = 0; i < 4000; i++) {
setTimeout(function () {
}, i)}
我收到一条警告,说[违规]“点击”处理程序耗时265毫秒。
为什么呢
背景:
我正在开发一个与音乐相关的应用程序,我们希望实现的功能之一是能够在循环中播放1000倍于1000倍的度量值,在用户体验方面类似于“无限”。如果一个度量值有4个注释,则需要设置1000*4个超时,这导致了这个巨大的性能问题。如果度量有16个音符,那么我的浏览器基本上就坏了^^
干杯
编辑:一些人建议根本不使用计时器来计时Web音频API-这是一个非常好的建议:
然而,对于我的应用程序,我们还制作了一个光标动画,显示要播放哪些音符,这需要设置超时时间,它会安排一个声音在指定时间开始播放。如果未指定时间,则声音立即开始播放
context = new AudioContext();
osc = context.createOscillator();
osc.connect(context.destination);
/* Schedule the start and stop times for the oscillator */
osc.start(context.currentTime + 2);
osc.stop(context.currentTime + 3);
使用AudioContext并将回调函数附加到振荡器节点的ONED事件。如果你想同时听音符的开头,那么你可以事先播放一个无声的音符,然后听它的结尾
上下文=新的音频上下文;
功能说明
频率
开始时间,
停下来,
启动(u)回调,,
停止呼叫
{
silent=context.create振荡器;
silent.frequency.setValueAtTime 0,context.currentTime
silent.startcontext.currentTime;
silent.stopcontext.currentTime+开始时间;
如果启动\u回调
{
silent.onedded=start\u回调;
}
osc=context.create振荡器;
osc.connectcontext.destination;
osc.startcontext.currentTime+启动时间;
osc.stopcontext.currentTime+停止时间;
osc.frequency.SetValueTime频率,context.currentTime+开始时间
如果停止,请返回
{
osc.onended=停止回调;
}
}
函数显示开始播放
{
this.classList.remove不播放,false;
this.classList.add playing,true;
}
函数显示停止播放
{
this.classList.remove playing,false;
this.classList.add not_playing,true;
}
注释={
A:{频率:440.00,元素:document.getElementById note_A},
B:{频率:493.88,元素:document.getElementById note_B},
C:{频率:523.25,元素:document.getElementById note_C},
D:{频率:587.33,元素:document.getElementById note_D},
}
剧本
注[A]。频率,
0,
1.
showStartedPlaying.bind notes[A].元素,
showStoppedPlaying.bind notes[A].元素,
剧本
注[B]。频率,
1.
2.
showStartedPlaying.bind notes[B]。元素,
showStoppedPlaying.bind notes[B]。元素,
剧本
注[C]。频率,
2.
3.
showStartedPlaying.bind notes[C].元素,
showStoppedPlaying.bind notes[C].元素,
剧本
注[D]。频率,
3.
4.
showStartedPlaying.bind notes[D]。元素,
showStoppedPlaying.bind notes[D]。元素,
.note{显示:内联块;宽度:2em;文本对齐:居中;}
.不播放{背景色:红色;}
.播放{背景色:绿色;}
a
b
c
d
为什么要为此使用setTimeout?使用并安排笔记。另一个可能更大的问题是setTimeout实际上并不能保证精确的计时。如果您想要“无限”,那么为什么要使用setTimeout,而不是setInterval?因为您可以立即创建4000个计时器,而计时器是一种资源。您只需要一个计时器就可以完成所需的操作。setInterval更糟糕。如果想执行setInterval,没有什么可以阻止在interalee函数中调用setTimeout。干杯,伙计,这段代码帮了我很大的忙!