Javascript 中的 sleep()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3136786/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
sleep() in Javascript
提问by nomind
Suppose I want to block Javascript execution for certain time for some weird reason, how can I do that. There is no sleep() in JS. Pls don't say do a while() loop because that's bad. I can do a window.showModalDialog and put a window.close in the modal dialog with setTimeout of very small time so that the user doesn't notice the dialog. This will be like sleep for small time period and I can call this multiple time if needed. Is there some other way?
假设我想出于某种奇怪的原因阻止 Javascript 执行一段时间,我该怎么做。JS 中没有 sleep()。请不要说执行 while() 循环,因为那很糟糕。我可以做一个 window.showModalDialog 并在模态对话框中放置一个 window.close , setTimeout 的时间非常短,这样用户就不会注意到对话框。这就像睡眠一小段时间,如果需要,我可以多次调用它。还有其他方法吗?
To elaborate, my use case is that HTML5 SQL Database has given async api's but I want to use it for a samll webapp for which the store will never be big. So there is no need of an async api because the queries on the small store will run on the client side. So I want to write an ORM with sync api so that developers can use it more easily. To bridge this async to sync api, I need something like sleep.
详细说明,我的用例是 HTML5 SQL 数据库提供了异步 api,但我想将它用于商店永远不会很大的小型 web 应用程序。因此不需要异步 api,因为小商店上的查询将在客户端运行。所以想写一个带有sync api的ORM,方便开发者使用。为了桥接这个异步到同步 api,我需要像 sleep 这样的东西。
回答by Russ Cam
window.setTimeoutor window.setIntervalare pretty much your only friends.
window.setTimeout或者window.setInterval几乎是你唯一的朋友。
An example of how to use setTimeoutto recursively call a function that sets another timeout is as follows
如何使用setTimeout递归调用设置另一个超时的函数的示例如下
function go() {
if (go.count < 4) {
// logs 1, 2, 3 to firebug console at 1 second intervals
console.log(go.count++);
window.setTimeout(go, 1000);
}
}
go.count = 1;
go();
You may choose to capture the timeoutID to use with window.clearTimeoutif you need to clear the timeout prior to it finishing.
window.clearTimeout如果您需要在完成之前清除超时,您可以选择捕获要使用的 timeoutID 。
Note that neither window.setTimeoutnor window.setIntervalblock execution of other script - I don't believe that this is possible with JavaScript in it's current guise. There are ways that could be coded to mimic UI blocking, such as using showModalDialogor having some global blockingboolean which are about as near as you can get I'm afraid.
请注意,既不会window.setTimeout也不会window.setInterval阻止其他脚本的执行 - 我不认为 JavaScript 在当前的伪装下是可能的。有一些方法可以编码来模拟 UI 阻塞,例如使用showModalDialog或使用一些全局blocking布尔值,这恐怕是你所能得到的。
回答by pkaeding
@Russ Cam is correct, setTimeoutis what you are looking for. The way you mentioned it in the question, though, makes me think that there might be some confusion about how it is used.
@Russ Cam 是正确的,setTimeout正是您要找的。但是,您在问题中提到它的方式让我认为可能对它的使用方式有些困惑。
It will not block execution of the block it is in, rather, it will call its input function after a certain interval. As an illustration:
它不会阻塞它所在块的执行,而是会在一定时间间隔后调用它的输入函数。举例说明:
function illustration() {
// start out doing some setup code
alert("This part will run first");
// set up some code to be executed later, in 5 seconds (5000 milliseconds):
setTimeout(function () {
alert("This code will run last, after a 5 second delay")
}, 5000);
// This code will run after the timeout is set, but before its supplied function runs:
alert("This will be the second of 3 alert messages to display");
}
You will see three alert messages when you run this function, with a delay between the second and third:
运行此函数时,您将看到三个警报消息,第二个和第三个之间有延迟:
- "This part will run first"
- "This will be the second of 3 alert messages to display"
- "This code will run last, after a 5 second delay"
- “这部分将首先运行”
- “这将是要显示的 3 条警报消息中的第二条”
- “此代码将在 5 秒延迟后最后运行”
回答by selfawaresoup
To clarify: The question is to halt the script execution completely for a certain amount of time, not to delay the execution of some piece of code, which wouild be a task for setTimeout or setInterval.
澄清:问题是在一定时间内完全停止脚本执行,而不是延迟某些代码的执行,这将是 setTimeout 或 setInterval 的任务。
A clean implementation of sleep() is just not possible and also not desireable in JavaScript.
sleep() 的干净实现在 JavaScript 中是不可能的,也是不可取的。
setTimout and setInterval do NOT halt the script execution like some people here seem top think. The just register a function to be run postponed. The rest of the script will continue running while the timeout/interval is waiting.
setTimout 和 setInterval 不会像这里的某些人认为的那样停止脚本执行。只是注册一个函数被推迟运行。在超时/间隔等待期间,脚本的其余部分将继续运行。
Due to the asynchronous nature of JavaScript, the only way to "block" any code execution would the very ugly and ABSOLUTELY NOT RECOMMENDED while loop that runs for a given amount of time. Since JavaScript itself runs in one single thread (we're not talking about WebWorkers API here ...). This would stop any JS code from being run until that loop finishes. But thats really bad style ...
由于 JavaScript 的异步特性,“阻止”任何代码执行的唯一方法是运行给定时间的非常丑陋且绝对不推荐的 while 循环。由于 JavaScript 本身在一个线程中运行(我们在这里不是在谈论 WebWorkers API ......)。这将停止运行任何 JS 代码,直到该循环完成。但那真的很糟糕的风格......
If your program can not work without something like sleep(), maybe you should rethink your approach.
如果你的程序没有 sleep() 之类的东西就无法运行,也许你应该重新考虑你的方法。
回答by Elf King
This answer may be a bit annoying but bare with it :-).
这个答案可能有点烦人,但没有办法:-)。
Since javascript is typically run inside a browser, which is multi-threaded of which javascript may occupying several threads, there is no concept of a "global sleep" the way you would have in a singly threaded program.
由于 javascript 通常在浏览器中运行,浏览器是多线程的,其中 javascript 可能占用多个线程,因此没有像在单线程程序中那样的“全局睡眠”概念。
If you want to pause an operation in any reasonable way you may want to consider the following.
如果您想以任何合理的方式暂停操作,您可能需要考虑以下内容。
Let's say you want to the following
假设您想要以下内容
function foo(s) {
var j = 1; var k = 1;
sleep(s); // This would be nice right?
window.alert("Sum is : " + (j+k));
}
Actually becomes:
实际上变成:
function foo(s) {
var j = 1 ; var k = 1;
setTimeout(s, function() {
window.alert("Sum is : " + (j+k));
});
}
Of course the problem is that in a procedural sense you may want to have something like
当然,问题是在程序意义上你可能想要像
function foo() {
do stuff;
pause();
do more stuff;
return;
}
function bar() {
foo(10);
window.alert("I want this to happen only after foo()");
}
The problem is that you can't really do that using setTimeout, as shown above
问题是你不能真正使用 setTimeout 做到这一点,如上所示
However you can do something like:
但是,您可以执行以下操作:
function foo(s, afterwards, afterparms) {
var j = 1 ; var k = 1;
setTimeout(s, function() {
window.alert("Sum is : " + (j+k));
afterparms.parm1 = afterparms.parm1.toUpperCase();
afterwards(afterparms);
});
}
function bar() {
foo(10, function() {
window.alert("This will happen after window.alert");
}, { parm1: 'hello', parm2: 'world' } );
}
Please note that above is only ONE way to go about passing information to functions, you can do some really cool stuff if you look up function calling conventions, variable arguments and such
请注意,以上只是将信息传递给函数的一种方式,如果您查找函数调用约定、变量参数等,您可以做一些非常酷的事情
This is annoying to program if you think procedurally. However, there are two things to remember regarding javascript. It is NOT a procedural language, NOR is it an object oriented language. Javascript is a functional language with a sophisticated event management model. So you have to think in those terms.
如果您按程序思考,这对编程来说很烦人。但是,关于 javascript,有两件事要记住。它不是过程语言,也不是面向对象的语言。Javascript 是一种具有复杂事件管理模型的函数式语言。所以你必须从这些方面思考。
It makes sense too, since the typical javascript machine is a gui (web browser) which by design do not want to completely block while trying to process something. Imagine your browser completely locking up while a page is doing something, you'd want to strangle the programmer who does that to you.
这也是有道理的,因为典型的 javascript 机器是一个 gui(网络浏览器),它在设计上不想在尝试处理某些东西时完全阻塞。想象一下你的浏览器在页面正在做某事时完全锁定,你想扼杀对你这样做的程序员。
Javascript code should be of 'fire-and-forget' nature, and if things have to wait for an event to occur before proceeding then you should be looking at the javascript event model.
Javascript 代码应该具有“即发即忘”的性质,如果事情必须等待事件发生才能继续,那么您应该查看 javascript 事件模型。
While this is inconvenient programming when you want to do something trivial, chances are you are using pause to wait in a way which may run into race conditions to begin with, and that there is a more appropriate way to go about the "effect" that you are attempting to achieve.
虽然当您想做一些微不足道的事情时,这是不方便的编程,但您可能正在使用暂停以一种可能会遇到竞争条件的方式等待,并且有一种更合适的方法来实现“效果”你正在努力实现。
If you post your PARTICULAR case, there may be more information forthcoming as to how one may address such a situation.
如果您发布您的 PARTICULAR 案例,可能会有更多关于如何解决这种情况的信息。
Cheers,
干杯,
回答by bobince
I can do a window.showModalDialog and put a window.close in the modal dialog with setTimeout of very small time
我可以做一个 window.showModalDialog 并在模态对话框中放置一个 window.close , setTimeout 的时间非常短
That's inventive, but it only allows for user interaction with anything in the modal dialog, for the length of time it's open. The rest of the browser remains hung as surely as if you'd just called a brutal while (new Date().getTime()<t1);loop.
这是创造性的,但它只允许用户与模态对话框中的任何内容进行交互,时间长短是打开的。浏览器的其余部分保持挂起,就像您刚刚调用了一个残酷的while (new Date().getTime()<t1);循环一样。
The modal dialog is kinder on CPU cycles and will avoid triggering the script-execution-time watchdog in the case of longer waits, but you'd have to balance that against the annoyance of a distracting flashing-open dialog box, and the non-universal browser support, and the issue of everyone hating modal dialogs!
模态对话框对 CPU 周期更友好,并且在等待时间较长的情况下将避免触发脚本执行时间看门狗,但您必须平衡它与分心的闪烁打开对话框的烦恼,以及非-通用浏览器支持,以及每个人都讨厌模态对话框的问题!
This will be like sleep for small time period and I can call this multiple time if needed. Is there some other way?
这就像睡眠一小段时间,如果需要,我可以多次调用它。还有其他方法吗?
What are you actually trying to achieve by sleeping? Without returning to the event loop or firing a modal dialog, you're not going to get any on-screen update or user interaction, so I don't see what an inline sleep is going to do for you. You certainly can't do animation this way.
你实际上想通过睡觉来达到什么目的?如果不返回事件循环或触发模态对话框,您将不会获得任何屏幕更新或用户交互,因此我不知道内联睡眠将为您做什么。你当然不能用这种方式做动画。
In Firefox you get Python-style generators, which would allow you to write a procedural-style interaction process using yieldto return control to the browser as necessary. This can improve the simplicity of code as you don't have to re-write conditional and looping structures as remembered state in variables. However as only Mozilla browsers support it you can't really use it in the wild for the foreseeable future.
在 Firefox 中,您可以获得 Python 风格的生成器,这将允许您编写一个过程风格的交互过程yield,用于在必要时将控制权返回给浏览器。这可以提高代码的简单性,因为您不必将条件和循环结构重写为变量中的记忆状态。然而,由于只有 Mozilla 浏览器支持它,因此在可预见的未来你不能真正在野外使用它。
ETA:
预计到达时间:
I want to write an ORM with sync api so that developers can use it more easily. To bridge this async to sync api, I need something like sleep.
我想写一个带有同步 api 的 ORM,以便开发人员可以更轻松地使用它。为了桥接这个异步到同步 api,我需要像 sleep 这样的东西。
Sorry, can't be done in the general case. Basic JavaScript does not have threads, co-routines or other primitives that can bridge sync and async code.
抱歉,一般情况下是做不到的。基本 JavaScript 没有线程、协同例程或其他可以桥接同步和异步代码的原语。
The Web SQL Database spec relies on browsers invoking your result-handling function (passed to executeSql()) as a browser callback. Browser callbacks can only fire when control has passed back to the browser, not inside a synchronous thread of execution.
Web SQL 数据库规范依赖于浏览器调用您的结果处理函数(传递给executeSql())作为浏览器回调。浏览器回调只能在控制权传递回浏览器时触发,而不是在同步执行线程内触发。
In theory, you could open a modalDialog, do the asynchronous Web SQL Database call insidethe modalDialog's window, and have the modalDialog return the result to synchronous code in the caller window's scripts. However, there is currently no browser that supports both openDatabaseandopenModalDialog!
从理论上讲,你可以打开一个modalDialog,做异步Web SQL数据库调用内部的modalDialog的窗口,并有modalDialog结果返回到调用程序窗口的脚本代码同步。但是,目前没有同时支持openDatabase和 的浏览器openModalDialog!
回答by Russ Bradberry
I know this question is a bit old, but I had a similar issue where I needed to simulate a script that took a long time to load on the page. I ended up solving the problem by creating a server side endpoint that waited 5 seconds before sending the response then added a script tag to the DOM to point to this.
我知道这个问题有点老,但我有一个类似的问题,我需要模拟一个需要很长时间才能在页面上加载的脚本。我最终通过创建一个服务器端端点来解决这个问题,该端点在发送响应之前等待 5 秒,然后向 DOM 添加一个脚本标记以指向它。
Granted it requires a server side implementation, however, it allows you to stop the page at any specific point. As others have said before, this will block the whole browser, not just your script.
当然,它需要服务器端实现,但是,它允许您在任何特定点停止页面。正如其他人之前所说,这将阻止整个浏览器,而不仅仅是您的脚本。

