检查 JavaScript setTimeout 是否已触发

发布于 2024-11-26 11:54:57 字数 326 浏览 0 评论 0原文

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

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

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

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

I'd like to be able to dispatch a bunch of work via JavaScript to be done in the browser in such a way that the browser stays responsive throughout.

The approach I'm trying to take is to chunk up the work, passing each chunk to a function that is then queued with a setTimeout(func, 0) call.

I need to know when all the work is done, so I'm storing the returned timer ID in a map (id -> true|false). This mapping is set to false in the next block of code after I have the timer ID, and the queued function sets the mapping to true when it completes... except, of course, the queued function doesn't know its timer ID.

Maybe there's a better/easier way... or some advice on how I can manipulate my map as I need to?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

狂之美人 2024-12-03 11:54:57

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

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

I would queue the work in an array, use one timeout to process the queue and call a callback once the queue is empty. Something like:

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!');
});

As JavaScript in browsers is single threaded there is no real advantage to run multiple timeouts (at least I think this is what you are doing). It may even slow down the browser.

情泪▽动烟 2024-12-03 11:54:57

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

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

I'd like to add that although javascript is single threaded you can still have multiple ajax calls going at once. I recently had a site that needed to do potentially hundreds of ajax calls and the browser just couldn't handle it. I created a queue that used setTimeOut to run 5 calls at once. When one of the ajax calls returned it fired a callback (which is handled by a single thread) and then made the next call on the stack.

Imagine you're a manager that can only talk to one person at a time, you give 5 employees assignments, then wait for their responses, which may come in any order. Once the first employee comes back and gives you the information, you give them a new assignment and wait for the next employee (or perhaps even the same employee) to come back. So although you're "single threaded" 5 things are going on at once.

小…红帽 2024-12-03 11:54:57

HTML 标准中有一个示例,最好如何处理:

要无任何延迟地连续运行几毫秒的任务,
同时仍然让步给浏览器以避免用户挨饿
界面(并避免浏览器杀死脚本来占用
CPU),只需在执行工作之前对下一个计时器进行排队即可:

函数 doExpectiveWork() {
  var 完成 = false;
  // ...
  // 这部分函数最多需要五毫秒
  // 如果完成则将done设置为true
  // ...
  返回完成;
}

函数重新安排工作(){
  var 句柄 = setTimeout(rescheduleWork, 0); // 预先安排下一次迭代
  如果(doExpuriousWork())
    清除超时(句柄); // 如果不需要则清除超时
}

函数计划工作(){
  setTimeout(重新安排工作, 0);
}

安排工作(); // 将任务排队以完成大量工作

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

There is an example right in the HTML Standard, how it is best to handle it:

To run tasks of several milliseconds back to back without any delay,
while still yielding back to the browser to avoid starving the user
interface (and to avoid the browser killing the script for hogging the
CPU), simply queue the next timer before performing work:

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

The moment of finishing the work is pretty clear, when clearTimeout is called.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文