检查是否已触发JavaScript setTimeout

时间:2011-07-27 13:19:52

标签: javascript queue settimeout

我希望能够通过JavaScript发送大量工作,以便浏览器始终保持响应。

我尝试采用的方法是将工作分块,将每个块传递给一个函数,然后使用setTimeout(func, 0)调用进行排队。

我需要知道所有工作何时完成,所以我将返回的计时器ID存储在地图中(id - > true | false)。在我有计时器ID之后,在下一个代码块中将此映射设置为false,并且排队函数在完成时将映射设置为true ...当然,排队函数不知道其计时器ID。

也许有更好/更简单的方法......或者我可以根据需要操作地图的一些建议?

3 个答案:

答案 0 :(得分:6)

我会将工作排入数组,使用一个超时来处理队列,并在队列为空时调用回调。类似的东西:

var work = [...];

var run = function(work, callback) {
    setTimeout(function() {
        if(work.length > 0) {
            process(work.shift());
            setTimeout(arguments.callee, 25);
        }
        else {
            callback();
        }
    }, 25);
};

run(work, function() {
    alert('Work is done!');
});

由于浏览器中的JavaScript是单线程的,因此运行多个超时没有任何实际优势(至少我认为这就是你正在做的事情)。它甚至可能会降低浏览器的速度。

答案 1 :(得分:1)

我想补充一点,虽然javascript是单线程的,但你仍然可以同时进行多个ajax调用。我最近有一个网站需要做数百个ajax调用,浏览器无法处理它。我创建了一个队列,使用setTimeOut一次运行5个调用。当其中一个ajax调用返回时,它触发了一个回调(由一个线程处理),然后在堆栈上进行下一次调用。

想象一下,你是一名经理,一次只能与一个人交谈,你给5名员工分配,然后等待他们的回复,这可能是任何顺序。一旦第一个员工回来并向您提供信息,您就会给他们一个新的任务并等待下一个员工(或者甚至是同一个员工)回来。因此,虽然你是“单线程”,但有5件事情同时发生。

答案 2 :(得分:0)

HTML Standard中有一个示例,说明如何最佳处理:

  

要无延迟地连续运行几毫秒的任务,   同时仍然让步回到浏览器以避免用户饿死   界面(并避免浏览器杀死用于拖累脚本的脚本   CPU),只需在执行工作之前将下一个计时器排队:

function doExpensiveWork() {
  var done = false;
  // ...
  // this part of the function takes up to five milliseconds
  // set done to true if we're done
  // ...
  return done;
}

function rescheduleWork() {
  var handle = setTimeout(rescheduleWork, 0); // preschedule next iteration
  if (doExpensiveWork())
    clearTimeout(handle); // clear the timeout if we don't need it
}

function scheduleWork() {
  setTimeout(rescheduleWork, 0);
}

scheduleWork(); // queues a task to do lots of work

调用clearTimeout时,完成工作的时刻非常清楚。