是否可以在javascript中实现sleep()?

时间:2015-01-29 15:49:10

标签: javascript multithreading sleep thread-sleep

这是一个重复的问题。之前已经多次询问,有几十个答案,其中一些评价非常高。不幸的是,据我所知,这些答案中的每一个答案都是"你不是,这不是一个糟糕的编程习惯。请改用setTimeout"。

这不是。一个。答案!

有一些用例 - 很少见,但它们存在 - 你可能希望整个页面的执行暂停一两秒,我觉得很沮丧,没有人似乎对回答实际问题感兴趣。 (看一些例子中的评论here)。

我确信可以暂停执行javascript;例如,如果我使用firebug插入断点,则执行在到达该点时停止。因此,萤火虫可以做到这一点。是否有某种方法程序可以暂停当前线程的执行,直到发生一些超时?

只是一些想法:萤火虫怎么做?是否有一些特定于浏览器的方法?是否可以触发停止,而不指定超时继续?我可以以编程方式插入断点,还是删除一个断点?我可以获得一个闭包,表示要传递给setTimeout的当前线程吗?

我没有考虑具体的用例;我只是想从比我更了解浏览器/ javascript设计的人那里寻求建议,以便最有效地完成这项工作。

到目前为止,我只提出了一个解决方案:

endtime=Date.now()+1000;
while(Date.now() < endtime)
    $.ajax(window.location.origin,{'async':false});

这似乎有效。它的问题是,它会产生数百个过多的请求。我会用mysite/sleep?delay=X之类的东西替换location.origin并写一个服务器端脚本来提供延迟,但是它会降低到1,但整个事情看起来仍然很糟糕。必须有更好的方法来做到这一点! jquery.ajax函数如何管理它?或者在某处埋葬了忙碌的等待?

以下内容没有回答这个问题而且会被低估,只是因为我厌倦了看到完全无视这些问题的答案页面,因为他们急于在睡眠中咆哮:

  • 睡觉是邪恶的,你应该做任何事情来避免需要它。
  • 重构您的代码,以便您可以使用setTimeout来延迟执行。
  • 忙碌等待(因为它在睡眠期间不会停止执行)。
  • 重构您的代码以使用deferred/promise语义。

2 个答案:

答案 0 :(得分:0)

你永远不应该这样做,这是一个坏主意......

...因为浏览器传统上是单线程的。睡眠会冻结用户界面和脚本。

然而,既然我们有网络工作者等,那并非如此。你可能不需要睡觉,但让工人忙碌等待却不会冻结用户界面。根据你想要冻结特定线程的程度,我见过人们使用:

endtime = Date.now()+1000;
while (Date.now() < endtime)

或者,奇怪的是(这是一个较旧但由企业赞助的分析库):

endtime = new Date().getTime() + 1000;
while (new Date().getTime() < endtime)

这可能比较慢。如果您正在忙碌等待,那不一定重要,分配对象可能只会耗费内存和GC时间。

使用承诺或超时的代码往往更模块化,但更难阅读(特别是当您第一次学习异步技术时)。这不是不使用它的借口,因为它有一定的优势,但也许你需要一切都能保持同步的原因。

如果你有一个调试器正在运行并希望一些代码块暂停(当你有一堆嵌套的回调函数时非常有用),你可以使用:

function foo() {
    do.someStuff();
    debugger;
    do.otherStuff();
}

浏览器应在调试器语句处暂停执行。调试器几乎总能暂停执行,因为它控制着运行代码的VM;它可以告诉VM停止运行,这应该发生。您无法从脚本中获得该级别,但如果您将source作为文本(可能来自require.js插件),您可以动态修改它以包含调试器语句,从而以编程方式提供#34;插入断点。&#34;请记住,只有在调试器已经打开时它们才会生效。

捕获&#34;线程的状态&#34;并坚持使用以供日后使用,您可能需要研究一些更复杂的函数式编程概念,尤其是monads。这些允许您将一个起始值包装在一系列函数中,这些函数会在它们运行时对其进行修改,但始终以相同的方式进行修改。你可以保持简单的状态(在某些对象中),或者记录和重现&#34;线程&#34;可能是通过在函数中包装函数来完成的。会有性能影响,但你可以稍后拿起最后一个函数并调用它,你应该能够重现线程可能做的所有事情。

这些都是相当复杂和具体使用的解决方案,以避免只是习惯性地推迟事情,但如果你假设需要它们,它们可能是有用的。

答案 1 :(得分:0)

不,在传统意义上的javascript中不可能实现睡眠,因为它是基于单线程事件的模型。睡眠此线程的行为将锁定其运行的浏览器,并向用户显示一条消息,告诉他们浏览器已停止响应(IE)或允许他们中止当前运行的代码(Firefox)。