关于html5:在Javascript中的sleep()

sleep() in Javascript

本问题已经有最佳答案,请猛点这里访问。

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

更详细地说,我的用例是HTML5 SQL数据库提供了AsyncAPI,但我想将其用于存储永远不会很大的Samll Web应用程序。所以不需要异步API,因为小存储上的查询将在客户端运行。所以我想用同步API编写一个ORM,这样开发人员可以更容易地使用它。要桥接这个异步到同步API,我需要睡眠之类的东西。


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

如何使用setTimeout递归调用设置另一个超时的函数的示例如下

1
2
3
4
5
6
7
8
9
10
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();

如果您需要在超时结束之前清除超时,可以选择捕获超时ID以与window.clearTimeout一起使用。

注意,无论是window.setTimeout还是window.setInterval都不会阻止其他脚本的执行-我不认为在当前的伪装下,使用javascript是可能的。有一些方法可以被编码来模仿用户界面阻塞,比如使用showModalDialog或者使用一些全局blocking布尔值,我想这大概是你能得到的。


@RussCam是对的,你要找的是setTimeout。不过,你在问题中提到它的方式让我觉得它的使用方式可能有些混乱。

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

1
2
3
4
5
6
7
8
9
10
11
12
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");
}

运行此功能时,您将看到三条警报消息,其延迟介于第二条和第三条之间:

  • "此部分将首先运行"
  • "这将是要显示的3条警报消息中的第二条"
  • 此代码将在延迟5秒后最后运行

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

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

    setimout和setinterval不会像这里的一些人认为的那样停止脚本的执行。只是注册一个要推迟运行的函数。当超时/间隔等待时,脚本的其余部分将继续运行。

    由于JavaScript的异步特性,唯一"阻止"任何代码执行的方法是非常难看的,绝对不推荐在循环运行一定时间后执行。因为JavaScript本身是在一个线程中运行的(我们这里不讨论WebWorkers API…)。这将停止任何JS代码的运行,直到循环结束。但那真是糟糕的风格…

    如果你的程序没有sleep()之类的东西就不能工作,也许你应该重新考虑一下你的方法。


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

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

    模式对话框在CPU周期上比较友好,在等待时间较长的情况下可以避免触发脚本执行时间监视器,但您必须平衡这一点,以防干扰闪烁的打开对话框,以及非通用浏览器支持,以及每个人都讨厌模式对话框的问题!

    This will be like sleep for small time period and I can call this multiple time if needed. Is there some other way?

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

    在firefox中,你会得到python风格的生成器,它允许你使用yield编写一个过程风格的交互过程,以便在必要时将控制权返回给浏览器。这可以提高代码的简单性,因为您不必将条件和循环结构重新编写为变量中的记忆状态。然而,由于只有Mozilla浏览器支持,在可预见的未来,您不能真正在野外使用它。

    埃塔:

    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.

    对不起,一般情况下不能做。基本的javascript没有线程、协同例程或其他可以桥接同步和异步代码的基元。

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

    理论上,您可以打开modaldialog,在modalDialog的窗口中执行异步Web SQL数据库调用,并让modaldialog将结果返回到调用方窗口脚本中的同步代码。但是,目前没有支持openDatabaseopenModalDialog的浏览器!


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

    由于javascript通常在多线程浏览器中运行,其中javascript可能占用多个线程,因此没有"全局休眠"的概念,就像在单线程程序中那样。

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

    假设你想

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

    实际上变成:

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

    当然,问题是,从程序的意义上讲,你可能想要

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function foo() {
       do stuff;
       pause();
       do more stuff;
       return;
    }

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

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

    但是,您可以执行以下操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     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(Web浏览器),按照设计,它不希望在处理某些东西时完全阻塞。想象一下,当一个页面在做某件事情时,你的浏览器完全锁定了,你会想扼杀对你这样做的程序员。

    javascript代码应该具有"失火和遗忘"的性质,如果在继续之前必须等待事件发生,那么您应该查看javascript事件模型。

    当你想做一些琐碎的事情时,这是不方便的编程,但很可能你正在使用暂停来等待,以一种可能会遇到竞争条件的方式开始,并且有一种更合适的方式来实现你试图达到的"效果"。

    如果你发布你的特定案例,你可能会得到更多关于如何处理这种情况的信息。

    干杯,


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

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