JavaScript睡眠

时间:2011-01-08 13:10:30

标签: javascript sleep

是的,我知道 - 这个问题有成千上万的答案。请不要告诉我有关setTimeout方法的信息,因为 - 是的,一切皆有可能,但不如使用sleep()方法那么容易。

例如:

function fibonacci(n) {
    console.log("Computing Fibonacci for " + n + "...");
    var result = 0;

    //wait 1 second before computing for lower n
    sleep(1000);
    result = (n <= 1) ? 1 : (fibonacci(n - 1) + fibonacci(n - 2));

    //wait 1 second before announcing the result
    sleep(1000);
    console.log("F(" + n + ") = " + result);

    return result;
}

如果你知道如何使用setTimeout获得相同的结果 - 请告诉我;)fibanacci是非常容易的任务,因为不会有超过2次递归,但是如何进行n次递归(如fib(1) )+ fib(2)+ .. + fib(n))并在每个“+”后睡觉?不,睡觉会轻松多了。

但我仍然无法实现它的实例。 while (curr - start < time) { curr = (...) }很棘手,但它不起作用(只需停止我的浏览器,然后立即抛出所有控制台日志)。

5 个答案:

答案 0 :(得分:31)

问题是询问如何在JavaScript中实现sleep(),对吗?

function sleep(ms) {
  var start = new Date().getTime(), expire = start + ms;
  while (new Date().getTime() < expire) { }
  return;
}

我刚刚测试过它:

console.log('hello');
sleep(5000);
console.log('world');

适合我。

(作为元评论:我在这里登陆是因为我特别需要这个功能。当你需要在等待值时阻塞时,会出现这样的需求。即使在JavaScript中也是如此。)

答案 1 :(得分:20)

我不完全明白你在问什么,但我会回答这一部分:

  

如果您知道如何获得相同的结果   使用setTimeout - 告诉我

根本区别在于sleep(在许多其他语言中使用)是同步的,而setTimeout(以及许多其他JavaScript概念,例如AJAX)是异步的。因此,为了重写您的功能,我们必须考虑到这一点。主要是,我们必须使用回调来获取“返回值”,而不是实际的返回语句,因此它将像这样使用:

fibonacci(7, function(result) {
  // use the result here..
});

所以,至于实施:

function fibonacci(n, callback) {
  console.log("Computing Fibonacci for " + n + "...");
  var result = 0;

  var announceAndReturn = function() {
    setTimeout(function() {
      // wait 1 second before announcing the result
      console.log("F(" + n + ") = " + result);
      callback(result); // "returns" the value
    }, 1000);
  };

  // wait 1 second before computing lower n
  setTimeout(function() {
    if (n <= 1) {
      result = 1;
      announceAndReturn();
    }
    else {
      var resultsLeft = 2;

      var handler = function(returned) {
        result += returned;
        resultsLeft--;
        if (resultLeft == 0)
          announceAndReturn();
      }

      fibonacci(n-1, handler);
      fibonacci(n-2, handler);
    }
  }, 1000);
}

我还想指出,没有,这不是比使用sleep更简单的解决方案。为什么?因为这段代码是异步的,而且比大多数人习惯的同步代码简单得多。以这种方式开始思考需要练习。

好处?它允许您编写优于同步对应的非阻塞算法。如果您之前没有听说过Node.js,可以查看它以进一步了解这一点的好处。 (许多其他语言也有用于处理异步IO的库,但只要谈论JavaScript ......)

答案 2 :(得分:3)

浏览器(或任何其他GUI环境)中sleep()类型函数的问题在于它是一个事件驱动的环境,并且无法sleep()进入你描述它的方式。

setTimeout()方法有效,因为它正在创建一个事件,并将该事件的触发器设置为一个时间点。因此系统可以过度控制等待事件处理程序,Javascript本身可以自由地进行其他事情。

在网络浏览器中,几乎所有东西都是这样的。鼠标单击/悬停/等功能是事件触发器。 Ajax请求不会等待来自服务器的响应;他们设置了一个事件,以便在收到回复时触发。

使用setTimeout()等功能,还可以使用事件触发器完成基于时间的操作。

这就是它的完成方式。事实上,这就是在几乎所有编写良好的GUI应用程序中完成的工作,因为所有GUI界面必须能够立即响应鼠标点击等事件。

一个Javascript sleep()函数(尤其是它在另一个答案中实现的方式!)基本上会在等待时钟时烧掉你的CPU周期。 sleep()仍然是活动过程,这意味着其他事件可能不会立即处理 - 这意味着您的浏览器似乎在睡眠期间停止响应鼠标点击等。不是一件好事。

setTimeout()是要走的路。总有办法做到这一点;结果代码可能不像你的示例代码那样整洁和线性,但事件驱动的代码很少是线性的 - 它不可能。解决方案是将过程分解为小功能。您甚至可以在setTimeout()调用中嵌入后续函数,这可能会帮助您保持代码至少具有线性外观。

希望这有助于为您解释一些事情。

答案 3 :(得分:2)

只使用a better algorithm没有循环或递归,并且无需setTimeout() / sleep()

function fibonacci(n) {
  return Math.round(Math.pow((Math.sqrt(5) + 1) / 2, Math.abs(n)) / Math.sqrt(5)) * (n < 0 && n % 2 ? -1 : 1);
}

用法示例:

// Log the first 10 Fibonacci numbers (F0 to F9) to the console
for (var i = 0; i < 10; i++) {
  console.log(fibonacci(i));
}

答案 4 :(得分:0)

为什么在计算任何东西时你想要“睡觉”?任何时候都在睡觉几乎在任何语言中总是一个坏主意。它基本上告诉线程在那段时间内停止做任何事情。

所以,在像javascript只有一个帖子(忘记'网络工作者')这样的语言中,你可以获得暂停所有计算的好处吗?这是一个坏主意,忘掉它。

现在谈到你写的问题,虽然我不认为这是你的实际问题。为什么要在计算此序列时暂停一秒钟?即使计算序列中的前6个数字,也需要8秒左右的时间。为什么?可能的原因是在递归调用之间暂停一秒钟?停下来。删除它。

如果你想在完成后的第二步产生最终结果,那么使用带有函数的setTimeout会以某种方式使用答案。

function fib(n) {
    ...
    result = fib();
    ...
    setTimeout(function() {
        console.log("Fib for " + n + " is " + result);
    },1000);
}

不要试图实现'睡眠'。在计算过程中不要暂停。