【问题标题】:Checking if a JavaScript setTimeout has fired检查 JavaScript setTimeout 是否已触发
【发布时间】:2011-10-14 06:31:12
【问题描述】:

我希望能够通过 JavaScript 分派一堆工作以在浏览器中完成,从而使浏览器始终保持响应。

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

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

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

【问题讨论】:

    标签: javascript queue settimeout


    【解决方案1】:

    我会在一个数组中排队工作,使用一个超时来处理队列,并在队列为空时调用回调。比如:

    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 是单线程的,因此运行多个超时并没有真正的优势(至少我认为这是您正在做的)。它甚至可能会降低浏览器的速度。

    【讨论】:

    • 好的,所以我认为主要的不同之处在于,这种方法在当前工作项完成时递归地设置下一个工作项的超时,而不是预先对所有项目设置超时并检查是否完成。我可以试一试...干杯
    【解决方案2】:

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

    假设您是一位一次只能与一个人交谈的经理,您给 5 名员工分配任务,然后等待他们的回复,这些回复可能以任意顺序出现。一旦第一个员工回来给你信息,你就给他们一个新的任务,然后等待下一个员工(或者甚至是同一个员工)回来。因此,尽管您是“单线程”,但同时发生了 5 件事。

    【讨论】:

      【解决方案3】:

      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被调用时。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-31
        • 1970-01-01
        • 1970-01-01
        • 2011-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多