【问题标题】:How can I ensure that the callback for setInterval is called exactly at the interval specified? [duplicate]如何确保 setInterval 的回调在指定的时间间隔内准确调用? [复制]
【发布时间】:2017-12-27 13:40:58
【问题描述】:

以这个函数为例:

function mySlowFunction(baseNumber) {
    console.time('mySlowFunction');
    var result = 0; 
    for (var i = Math.pow(baseNumber, 10); i >= 0; i--) {       
        result += Math.atan(i) * Math.tan(i);
    };
    console.timeEnd('mySlowFunction');
    return result;
}

这是一个占用大量 CPU 资源的函数。 mySlowFunction(5) 大约需要 3 秒才能完成。

现在考虑这段代码:

setInterval(() => console.log("interval"), 1000); 
mySlowFunction(5);

我希望它每秒记录一次“间隔”,但我知道由于 mySlowFunction 在线程上运行并且 JS 是单线程的,所以 setInterval 的回调仅在 mySlowFunction 完成后执行。

有什么方法可以确保在指定的时间间隔内调用回调?我希望在基于浏览器的环境中使用它。

【问题讨论】:

  • 你根本不应该在几秒钟内用任何东西阻塞主线程。如果您有一些密集的计算要做,请将它们放入 web worker 中或使用setTimeout 将它们分解为可中断的块。
  • 我不相信你可以确定这一点,正是因为你所说的原因:JS 是单线程的。我认为没有办法解决这个问题。

标签: javascript


【解决方案1】:

您不应该期望间隔会在指定的延迟时触发。
Here -> ( Reasons for delays longer than specified ) 是延迟可能比预期更长的几个原因。无论如何,如果您仍想确保在您的 mySlowFunction 完成执行之前触发您的间隔,您可以如 cmets 中所述使用 Worker

Web Workers API 的 Worker 接口代表一个后台任务,可以轻松创建并可以将消息发送回其创建者。

mySlowFunction 的计算分配给不同的线程。

这是一个例子:

var blobWorker = URL.createObjectURL( new Blob([ '(',
    function() {
        self.onmessage = function(e) {
          
        	var result = 0; 
        	for (var i = Math.pow(e.data, 10); i >= 0; i--) {
            result += Math.atan(i) * Math.tan(i);
        	};
        	
          self.postMessage(result);
        };
    }.toString(),
')()' ], { type: 'application/javascript' } ) );

var worker = new Worker( blobWorker );

worker.onmessage = function(e) {

    console.log("result from mySlowWorker:", e.data);
}

var intervalId = setInterval(() => console.log("interval"), 1000);

worker.postMessage(5);

URL.revokeObjectURL( blobWorker );

setTimeout( _ => { clearInterval(intervalId); console.log('done') }, 5000)

【讨论】:

    【解决方案2】:

    Javascript 不保证计时器延迟。由于 Javascript 的单线程特性,异步事件(例如计时器和鼠标单击)一次执行一个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多