JavaScript 中的 sleep()

发布于 2024-09-07 01:02:40 字数 394 浏览 6 评论 0 原文

假设我想出于某种奇怪的原因阻止 Javascript 执行一段时间,我该怎么做。 JS 中没有 sleep() 。请不要说执行 while() 循环,因为那很糟糕。我可以做一个 window.showModalDialog 并在模式对话框中放置一个 window.close ,并且 setTimeout 的时间非常短,这样用户就不会注意到该对话框。这就像一小段时间的睡眠,如果需要,我可以多次调用它。还有其他办法吗?

详细来说,我的用例是 HTML5 SQL 数据库提供了异步 api,但我想将它用于一个小型 Web 应用程序,该应用程序的商店永远不会很大。因此不需要异步 api,因为小商店上的查询将在客户端运行。所以我想写一个带有sync api的ORM,以便开发者可以更方便地使用它。为了桥接这个异步到同步 api,我需要像 sleep 这样的东西。

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?

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.

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

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

发布评论

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

评论(6

醉态萌生 2024-09-14 01:02:40

window.setTimeoutwindow.setInterval 几乎是您唯一的朋友。

如何使用 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();

您可以选择捕获 timeoutID 以与 window.clearTimeout 如果您需要在完成之前清除超时。

请注意, window.setTimeoutwindow.setInterval 阻止其他脚本的执行 - 我不相信这对于当前的 JavaScript 来说是可能的。有一些方法可以通过编码来模拟 UI 阻塞,例如使用 showModalDialog 或使用一些全局 blocking 布尔值,恐怕这是您能得到的最接近的值。

window.setTimeout or window.setInterval are pretty much your only friends.

An example of how to use setTimeout to recursively call a function that sets another timeout is as follows

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.clearTimeout if you need to clear the timeout prior to it finishing.

Note that neither window.setTimeout nor window.setInterval block 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 showModalDialog or having some global blocking boolean which are about as near as you can get I'm afraid.

七秒鱼° 2024-09-14 01:02:40

@Russ Cam 是正确的,setTimeout 就是您正在寻找的。不过,您在问题中提到它的方式让我认为它的使用方式可能存在一些混乱。

它不会阻止其所在块的执行,而是会在一定时间间隔后调用其输入函数。举例来说:

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");
}

运行此函数时,您将看到三条警报消息,第二条和第三条之间有延迟:

  1. “这部分将首先运行”
  2. “这将是要显示的 3 条警报消息中的第二条”
  3. “此代码将运行最后,延迟 5 秒后”

@Russ Cam is correct, setTimeout is 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.

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:

  1. "This part will run first"
  2. "This will be the second of 3 alert messages to display"
  3. "This code will run last, after a 5 second delay"
谁许谁一生繁华 2024-09-14 01:02:40

澄清一下:问题是完全停止脚本执行一段时间,而不是延迟某些代码的执行,这将是 setTimeout 或 setInterval 的任务。

一个干净的实现sleep() 在 JavaScript 中是不可能的,也是不可取的。

setTimout 和 setInterval 不会像这里有些人认为的那样停止脚本执行。只需注册一个要推迟运行的函数即可。在超时/间隔等待期间,脚本的其余部分将继续运行。

由于 JavaScript 的异步特性,“阻止”任何代码执行的唯一方法是非常丑陋且绝对不推荐运行给定时间的 while 循环。
由于 JavaScript 本身在一个单线程中运行(我们这里不讨论 WebWorkers API ...)。这将阻止任何 JS 代码运行,直到该循环完成。但这真的很糟糕......

如果你的程序没有像 sleep() 这样的东西就无法工作,也许你应该重新考虑你的方法。

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.

A clean implementation of sleep() is just not possible and also not desireable in 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.

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 ...

If your program can not work without something like sleep(), maybe you should rethink your approach.

べ映画 2024-09-14 01:02:40

这个答案可能有点烦人,但也很简单:-)。

由于 javascript 通常在浏览器内运行,浏览器是多线程的,其中 javascript 可能占用多个线程,因此不存在单线程程序中那样的“全局睡眠”概念。

如果您想以任何合理的方式暂停操作,您可能需要考虑以下事项。

假设您想要以下内容

function foo(s) {
    var j = 1; var k = 1;
    sleep(s); // This would be nice right?  
    window.alert("Sum is : " + (j+k));
}

实际上会变成:

function foo(s) {
     var j = 1 ; var k = 1;
     setTimeout(s, function() { 
            window.alert("Sum is : " + (j+k));
     });
}

当然,问题是,从程序意义上讲,您可能想要类似的东西

function foo() {
   do stuff;
   pause();
   do more stuff;
   return;
}

function bar() {
      foo(10);
      window.alert("I want this to happen only after foo()");
}

问题是,您不能真正使用 setTimeout 做到这一点,如上所示

但是您可以这样做:

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

请注意,上面只是将信息传递给函数的一种方法,如果您查找函数调用约定、变量参数等,您可以做一些非常酷的事情

如果您按程序思考。然而,关于 javascript 有两件事需要记住。它不是一种过程语言,也不是一种面向对象的语言。 Javascript 是一种具有复杂事件管理模型的函数式语言。所以你必须从这些角度思考。

这也是有道理的,因为典型的 javascript 机器是一个 gui(网络浏览器),它在设计上不想在尝试处理某些内容时完全阻塞。想象一下,当页面正在执行某些操作时,您的浏览器完全锁定,您会想掐死对您执行此操作的程序员。

Javascript 代码应该具有“即发即忘”的性质,如果必须等待事件发生才能继续,那么您应该查看 javascript 事件模型。

虽然当您想做一些琐碎的事情时,这是不方便的编程,但您很可能使用暂停来等待,这种方式可能会在一开始就遇到竞争条件,并且有一种更合适的方法来实现以下“效果”:你正在努力实现。

如果您发布您的特定案例,可能会提供更多关于如何解决此类情况的信息。

干杯,

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.

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

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.

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 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.

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.

Cheers,

雄赳赳气昂昂 2024-09-14 01:02:40

我可以做一个window.showModalDialog,并在模式对话框中放置一个window.close,setTimeout时间非常短

这是创造性的,但它只允许用户在模式对话框打开的时间内与模式对话框中的任何内容进行交互。浏览器的其余部分仍然挂起,就像您刚刚调用了一个残酷的 while (new Date().getTime() 循环一样。

模式对话框对 CPU 周期更友好,并且可以避免在等待较长时间的情况下触发脚本执行时间看门狗,但您必须在分散注意力的闪烁打开对话框和非-通用浏览器支持,以及每个人都讨厌模式对话框的问题!

这就像一小段时间的睡眠,如果需要,我可以多次调用它。还有其他办法吗?

你到底想通过睡眠达到什么目的?如果不返回事件循环或触发模式对话框,您将不会获得任何屏幕更新或用户交互,因此我不知道内联睡眠将为您做什么。你当然不能用这种方式制作动画。

在 Firefox 中,您可以获得 Python 风格的 生成器,它允许您编写程序式交互过程,根据需要使用 yield 将控制权返回给浏览器。这可以提高代码的简单性,因为您不必将条件和循环结构重写为变量中记住的状态。然而,由于只有 Mozilla 浏览器支持它,因此在可预见的将来你无法真正在野外使用它。

预计到达时间:

我想写一个带有sync api的ORM,以便开发者可以更方便地使用它。为了桥接这个异步与同步 api,我需要诸如 sleep 之类的东西。

抱歉,一般情况下无法完成。基本 JavaScript 没有线程、协同例程或其他可以桥接同步和异步代码的原语。

Web SQL 数据库规范依赖于浏览器调用结果处理函数(传递给 executeSql())作为浏览器回调。浏览器回调只能在控制权传回浏览器时触发,而不能在同步执行线程内触发。

理论上,您可以打开一个 modalDialog,在 modalDialog 窗口内执行异步 Web SQL 数据库调用,然后让 modalDialog 将结果返回给调用方中的同步代码窗口的脚本。但是,目前还没有浏览器同时支持 openDatabase openModalDialog

I can do a window.showModalDialog and put a window.close in the modal dialog with setTimeout of very small time

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.

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!

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 yield to 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.

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.

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.

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.

In theory, you could open a modalDialog, do the asynchronous Web SQL Database call inside the 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 openDatabase and openModalDialog!

稀香 2024-09-14 01:02:40

我知道这个问题有点老了,但我遇到了类似的问题,我需要模拟一个需要很长时间才能在页面上加载的脚本。我最终通过创建一个服务器端端点来解决这个问题,该端点在发送响应之前等待 5 秒,然后向 DOM 添加一个脚本标记来指向它。

尽管它需要服务器端实现,但是,它允许您在任何特定点停止页面。正如其他人之前所说,这将阻止整个浏览器,而不仅仅是您的脚本。

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.

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.

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