如何检查Javascript setTimeout队列?

时间:2014-05-13 18:26:47

标签: javascript

我有一个非常复杂的JS应用程序,它通过setTimeout()在可能的情况下排队许多逻辑。这对于防止IE7 / 8中的慢速脚本警告是必要的。

我知道。我希望我也不必支持这些。

无论如何,我需要知道所有这些操作何时完成,以便我可以为用户解锁UI。

有没有办法检查JS任务队列?

3 个答案:

答案 0 :(得分:1)

你可以计算你已经启动了多少块,并计算每个块的减少量,检查它是否为零,如果是,则运行完成逻辑。

答案 1 :(得分:1)

我认为你不能在任何浏览器中都这样做。

但是,您可以使用Promise pattern在异步操作完成时通知某人。

这是一个使用jQuery's promise implementation的简单示例,使用setTimeout分解执行,因此不会警告用户执行时间太长的脚本:

// a factory for promises
function createPromiseFor(doWork) {
    // create a deferred object
    var deferred = $.Deferred();

    // a function that will schedule our work;
    function scheduleMoreWork() {
        setTimeout(function () {

            // doWork does at least some of the work, and tells us when it is done
            var finished = doWork();

            if (finished) {
                deferred.resolve();
            } else {
                scheduleMoreWork();
            }
        }, 1);
    };

    // schedule the first one
    scheduleMoreWork();

    return deferred.promise();
}

// assuming ourFunction does its work in chunks and can resume from where it left off...
var promise = createPromiseFor(ourFunction);
promise.done(function () {
    alert('done!');
});

这是一个可以暂停的函数示例,并在下次调用时恢复:

var fn = (function () {
    var goal = 100,
        iterationsPerInvocation = 10,
        current = 0;

    function invoke() {
        for (var i = 0; i < iterationsPerInvocation; ++i) {
            current++;
        }
    }

    return function () {
        invoke();
        return current === goal;
    }
})();

var promise = createPromiseFor(fn);
promise.done(function () {
    alert('done!');
});

答案 2 :(得分:0)

意识到这是一个过时的线程,但是遇到了类似的需要将任务排队的问题,并且可以选择清除javascript setTimeout队列中的冗余任务,因为进程队列开始清空...

实质上包装了setTimeout和clearTimeout函数,以使用Map(名为setTimeoutQueue)来跟踪setTimeout进程队列。 (此函数包装技术并不是什么新鲜事物,正如我所见,它与自定义事件处理程序混合器一起使用,该混合器可抢占对象或类的preempt和postempt(?)方法。)核心概念是,进程从队列中弹出,活动进程可以搜索setTimeoutQueue以确定是否有多余的任务坐在队列中,如果是,则使用抢占式的clearTimeout函数来清除实际排队的进程和setTimeoutQueue跟踪的相应任务条目。

const actualSetTimeout = setTimeout;
const actualClearTimeout = clearTimeout;

setTimeoutQueue = new Map();

setTimeout = function(f, ms, ...fArgs) {

  console.log(`setTimeout "${f}" - BEFORE QUEUING TASK.`);
  console.log(setTimeoutQueue);

  const setTimeoutHandle = actualSetTimeout(
    function() {
      console.log(`setTimeout "${f}" - BEFORE EXECUTION.`);
      console.log(setTimeoutQueue);

      const fResult = f(...fArgs);
      setTimeoutQueue.delete(setTimeoutHandle);

      console.log(`setTimeout "${f}" - AFTER EXECUTION.`);
      console.log(setTimeoutQueue);
      return fResult;
    },
    ms,
    ...fArgs
  );

  setTimeoutQueue.set(setTimeoutHandle, [f, ms, ...fArgs]);

  console.log(`setTimeout "${f}" - AFTER QUEUING TASK.`);
  console.log(setTimeoutQueue);

  return setTimeoutHandle;
}

clearTimeout = function(id) {
  actualClearTimeout(id);
  setTimeoutQueue.delete(id);
}

console.log(setTimeoutQueue);
setTimeout((...args)=>{console.log(`5 sec timer fired with params = ${args}`)}, 5000, 555, 5555);
setTimeout((x)=>{console.log(`2 sec timer fired with first param = ${x}`)}, 2000, 222);
setTimeout(()=>{console.log(`Queued for immediate execution.`)});
console.log(setTimeoutQueue);

很明显,除了表示自定义代码注入点之外,所有的“ console.logs”都可以帮助理解执行顺序。我仅有的不确定性是抢占setTimeout和clearTimeout函数的任何副作用,但是时间和建设性的批评会告诉您...;-)