为什么在Javascript中在循环中调用setTimeout要求这么高?

为什么在Javascript中在循环中调用setTimeout要求这么高?,javascript,Javascript,TLDR: 在Chrome OSX中运行以下JS代码时: for (let i = 0; i < 4000; i++) { setTimeout(function () { }, i)} 我收到一条警告,说[违规]“点击”处理程序耗时265毫秒。 为什么呢 背景: 我正在开发一个与音乐相关的应用程序,我们希望实现的功能之一是能够在循环中播放1000倍于1000倍的度量值,在用户体验方面类似于“无限”。如果一个度量值有4个注释,则需要设置1000*4个超时,这导致了这个巨大的性能问

TLDR: 在Chrome OSX中运行以下JS代码时:

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。干杯,伙计,这段代码帮了我很大的忙!