sleep() 的 JavaScript 版本是什么?

发布于 2024-07-24 03:26:55 字数 501 浏览 8 评论 0 原文

有没有比下面的 pausecomp 函数(取自此处)?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

这不是 JavaScript 中的睡眠 - 操作之间的延迟的重复项; 我想要在函数中间有一个真正的睡眠,而不是在一段代码执行之前延迟。

Is there a better way to engineer a sleep in JavaScript than the following pausecomp function (taken from here)?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

This is not a duplicate of Sleep in JavaScript - delay between actions; I want a real sleep in the middle of a function, and not a delay before a piece of code executes.

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

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

发布评论

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

评论(30

最冷一天 2024-07-31 03:26:55

2017 - 2021 更新

自 2009 年提出这个问题以来,JavaScript 已经发生了显着的发展。 所有其他答案现在都已过时或过于复杂。 这是当前的最佳实践:

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

或者作为单行:

await new Promise(r => setTimeout(r, 2000));

作为函数:

const sleep = ms => new Promise(r => setTimeout(r, ms));

或者在 Typescript 中:

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

将其用作:

await sleep(<duration>);

演示:

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
    for (let i = 0; i < 5; i++) {
        console.log(`Waiting ${i} seconds...`);
        await sleep(i * 1000);
    }
    console.log('Done');
}

demo();

请注意,

  1. await 只能在以 async 关键字为前缀的函数中执行,或者在 越来越多的环境
  2. await 仅暂停当前的 async 函数。 这意味着它不会阻止脚本其余部分的执行,这正是您在绝大多数情况下所希望的。 如果您确实想要阻塞构造,请参阅此答案 使用 Atomics.wait,但请注意,大多数浏览器不允许在浏览器的主线程上使用它。

两个新的 JavaScript 功能(截至 2017 年)帮助编写了这个“睡眠”函数:

兼容性

如果由于某种原因,您使用的 Node 版本超过 7(已于 2017 年达到生命周期结束),或者针对旧浏览器,仍然可以通过 async/await "noreferrer">Babel(一种转译< /a> JavaScript + 新功能转换为普通的旧 JavaScript),使用 transform-async-to-generator 插件。

2017 — 2021 update

Since 2009 when this question was asked, JavaScript has evolved significantly. All other answers are now obsolete or overly complicated. Here is the current best practice:

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

Or as a one-liner:

await new Promise(r => setTimeout(r, 2000));

As a function:

const sleep = ms => new Promise(r => setTimeout(r, ms));

or in Typescript:

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

use it as:

await sleep(<duration>);

Demo:

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
    for (let i = 0; i < 5; i++) {
        console.log(`Waiting ${i} seconds...`);
        await sleep(i * 1000);
    }
    console.log('Done');
}

demo();

Note that,

  1. await can only be executed in functions prefixed with the async keyword, or at the top level of your script in an increasing number of environments.
  2. await only pauses the current async function. This means it does not block the execution of the rest of the script, which is what you want in the vast majority of the cases. If you do want a blocking construct, see this answer using Atomics.wait, but note that most browsers will not allow it on the browser's main thread.

Two new JavaScript features (as of 2017) helped write this "sleep" function:

Compatibility

If for some reason you're using Node older than 7 (which reached end of life in 2017), or are targeting old browsers, async/await can still be used via Babel (a tool that will transpile JavaScript + new features into plain old JavaScript), with the transform-async-to-generator plugin.

温柔戏命师 2024-07-31 03:26:55

(请参阅 2016 年更新的答案

我认为想要执行一个操作,等待,然后执行另一个操作是完全合理的行动。 如果您习惯于使用多线程语言进行编写,您可能会有在设定的时间内让出执行直到线程唤醒的想法。

这里的问题是 JavaScript 是一个基于事件的单线程模型。 虽然在特定情况下,让整个引擎等待几秒钟可能会更好,但一般来说这是不好的做法。 假设我想在编写自己的函数时使用您的函数? 当我调用你的方法时,我的方法都会冻结。 如果 JavaScript 能够以某种方式保留函数的执行上下文,将其存储在某个地方,然后将其返回并稍后继续,那么睡眠可能会发生,但这基本上就是线程。

因此,您几乎被其他人的建议所困扰——您需要将代码分解为多个函数。

那么你的问题是有点错误的选择。 没有办法以你想要的方式睡觉,你也不应该追求你建议的解决方案。

(See the updated answer for 2016)

I think it's perfectly reasonable to want to perform an action, wait, and then perform another action. If you are used to writing in multi-threaded languages, you probably have the idea of yielding execution for a set amount of time until your thread wakes up.

The issue here is that JavaScript is a single-thread event-based model. While in a specific case, it might be nice to have the whole engine wait for a few seconds, in general it is bad practice. Suppose I wanted to make use of your functions while writing my own? When I called your method, my methods would all freeze up. If JavaScript could somehow preserve your function's execution context, store it somewhere, then bring it back and continue later, then sleep could happen, but that would basically be threading.

So you are pretty much stuck with what others have suggested -- you'll need to break your code up into multiple functions.

Your question is a bit of a false choice, then. There is no way to sleep in the way you want, nor should you pursue the solution you suggest.

秋千易 2024-07-31 03:26:55

在 JavaScript 中,我重写了每个函数,以便它能够尽快结束。 您希望浏览器重新获得控制权,以便它可以更改您的 DOM。

每次我想要在函数中间休息时,我都会重构以使用 setTimeout()

编辑

任何语言中臭名昭著的睡眠或延迟功能都备受争议。 有些人会说应该始终有一个信号或回调来触发给定的功能,其他人会认为有时任意的延迟时刻是有用的。 我想说的是,每个人都有自己的规则,一条规则永远不能决定这个行业的任何事情。

编写 sleep 函数很简单,并且通过 JavaScript Promises 变得更加有用:

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});

如果您在 async 函数中,您可以使用上面的 sleep()

// Available inside async functions:
await sleep(500);

// Do something after the sleep…

In JavaScript, I rewrite every function so that it can end as soon as possible. You want the browser back in control so it can make your DOM changes.

Every time I've wanted a sleep in the middle of my function, I refactored to use a setTimeout().

Edit

The infamous sleep, or delay, function within any language is much debated. Some will say that there should always be a signal or callback to fire a given functionality, others will argue that sometimes an arbitrary moment of delay is useful. I say that to each their own and one rule can never dictate anything in this industry.

Writing a sleep function is simple and made even more usable with JavaScript Promises:

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});

If you are inside an async function you can do a proper await step with the above definition of sleep():

// Available inside async functions:
await sleep(500);

// Do something after the sleep…
盗琴音 2024-07-31 03:26:55

Firebug (可能还有其他 JavaScript 控制台)中,按 Enter 键后什么也没有发生,只是在指定的睡眠持续时间之后 (...)

function sleepFor(sleepDuration){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* Do nothing */ }
}

使用示例:

function sleepFor(sleepDuration){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ 
        /* Do nothing */ 
    }
}

function sleepThenAct(){
    sleepFor(2000);
    console.log("Hello, JavaScript sleep!");
}

sleepThenAct()

注意:仅用于调试和开发

In Firebug (and probably other JavaScript consoles), nothing happen after hitting enter, only after the sleep duration specified (...)

function sleepFor(sleepDuration){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* Do nothing */ }
}

Example of use:

function sleepFor(sleepDuration){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ 
        /* Do nothing */ 
    }
}

function sleepThenAct(){
    sleepFor(2000);
    console.log("Hello, JavaScript sleep!");
}

sleepThenAct()

Note: Only for debugging and development

流殇 2024-07-31 03:26:55

我同意其他海报的观点。 忙碌的睡眠只是一个坏主意。

但是,setTimeout 不会阻止执行。 它在超时设置后立即执行函数的下一行,而不是在超时到期后执行,因此不会完成与睡眠相同的任务。

做到这一点的方法是将你的函数分解为前后部分。

function doStuff()
{
  // Do some things
  setTimeout(continueExecution, 10000) // Wait ten seconds before continuing
}

function continueExecution()
{
   // Finish doing things after the pause
}

确保您的函数名称仍然准确地描述了每个部分正在执行的操作(即 GatherInputThenWait 和 CheckInput,而不是 funcPart1 和 funcPart2)。

此方法实现了不执行您决定的代码行的目的,直到之后超时,同时仍将控制权返回给客户端 PC 以执行其已排队的任何其他操作。

正如评论中所指出的,这绝对不会在循环中工作。 你可以做一些花哨的(丑陋的)黑客让它在循环中工作,但一般来说,这只会产生灾难性的意大利面条代码。

I agree with the other posters. A busy sleep is just a bad idea.

However, setTimeout does not hold up execution. It executes the next line of the function immediately after the timeout is SET, not after the timeout expires, so that does not accomplish the same task that a sleep would accomplish.

The way to do it is to breakdown your function into before and after parts.

function doStuff()
{
  // Do some things
  setTimeout(continueExecution, 10000) // Wait ten seconds before continuing
}

function continueExecution()
{
   // Finish doing things after the pause
}

Make sure your function names still accurately describe what each piece is doing (i.e., GatherInputThenWait and CheckInput, rather than funcPart1 and funcPart2)

This method achieves the purpose of not executing the lines of code you decide until after your timeout, while still returning control back to the client PC to execute whatever else it has queued up.

As pointed out in the comments this will absolutely not work in a loop. You could do some fancy (ugly) hacking to make it work in a loop, but in general that will just make for disastrous spaghetti code.

南笙 2024-07-31 03:26:55

为了对 $DEITY 的热爱,请不要设置忙等待睡眠功能。 setTimeoutsetInterval 可以完成您需要的一切。

var showHide = document.getElementById('showHide');
setInterval(() => {
    showHide.style.visibility = "initial";
    setTimeout(() => {
        showHide.style.visibility = "hidden"
    }, 1000);
}, 2000);   
<div id="showHide">Hello! Goodbye!</div>

每两秒间隔隐藏文本一秒。 这展示了如何使用 setInterval 和 setTimeout 每秒显示和隐藏文本。

For the love of $DEITY please do not make a busy-wait sleep function. setTimeout and setInterval do everything you need.

var showHide = document.getElementById('showHide');
setInterval(() => {
    showHide.style.visibility = "initial";
    setTimeout(() => {
        showHide.style.visibility = "hidden"
    }, 1000);
}, 2000);   
<div id="showHide">Hello! Goodbye!</div>

Every two second interval hide text for one second. This shows how to use setInterval and setTimeout to show and hide text each second.

心房的律动 2024-07-31 03:26:55

如果(像我一样)您将 JavaScript 与 Rhino 一起使用,您可以使用...

try
{
  java.lang.Thread.sleep(timeInMilliseconds);
}
catch (e)
{
  /*
   * This will happen if the sleep is woken up - you might want to check
   * if enough time has passed and sleep again if not - depending on how
   * important the sleep time is to you.
   */
}

If (like me) you're using JavaScript with Rhino, you can use...

try
{
  java.lang.Thread.sleep(timeInMilliseconds);
}
catch (e)
{
  /*
   * This will happen if the sleep is woken up - you might want to check
   * if enough time has passed and sleep again if not - depending on how
   * important the sleep time is to you.
   */
}
知你几分 2024-07-31 03:26:55

使用:

await new Promise(resolve => setTimeout(resolve, 2000));

在异步函数内。

Use:

await new Promise(resolve => setTimeout(resolve, 2000));

inside an async function.

掀纱窥君容 2024-07-31 03:26:55

如果您使用 jQuery,实际上有人创建了一个“延迟”插件,它只不过是 setTimeout 的包装器:

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
        setTimeout(func,time);
    });

    return this;
};

然后您可以按预期在一行函数调用中使用它:

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');

If you're using jQuery, someone actually created a "delay" plugin that's nothing more than a wrapper for setTimeout:

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
        setTimeout(func,time);
    });

    return this;
};

You can then just use it in a row of function calls as expected:

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');
暖风昔人 2024-07-31 03:26:55
  1. 标准 JavaScript:

    定义异步睡眠函数:

    const sleep = (ms: number) =>;   new Promise((resolve) => setTimeout(resolve, ms)) 
      

    并使用它:

    await sleep(1000) // 睡眠 1 秒 
      

  1. Bun.js原生实现了上述功能:

    await Bun.sleep(1000) // 休眠 1 秒 
      

    参见:https://bun.sh/guides/util/sleep


  1. Node.js

    自 Node.js 16+ 起,新的承诺版本setTimeout() 可用

    从 'timers/promises' 导入 {setTimeout} 
    
      wait setTimeout(1000) // 休眠1秒 
      

    参见:https://nodejs.org/api/timers.html #timerspromisessettimeoutdelay-value-options

  1. Standard JavaScript:

    Define async sleep function:

    const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
    

    and use it:

    await sleep(1000) // Sleep for 1 second
    

  1. Bun.js has natively implmented the above function:

    await Bun.sleep(1000) // Sleep for 1 second
    

    See: https://bun.sh/guides/util/sleep


  1. Node.js:

    Since Node.js 16+ a new promisified version of setTimeout() is available:

    import {setTimeout} from 'timers/promises'
    
    await setTimeout(1000) // Sleep for 1 second
    

    See: https://nodejs.org/api/timers.html#timerspromisessettimeoutdelay-value-options

简单爱 2024-07-31 03:26:55

我也搜索了睡眠解决方案(不适用于生产代码,仅用于开发和测试)并找到了这篇文章:

JavaScript sleep() 或 wait()

...这是另一篇有关客户端解决方案的文章:JavaScript sleep

另外,当您调用 alert() 时,您的代码将在显示警报时也暂停 - 您需要找到一种方法来不显示警报,但获得相同的效果。 :)

I've searched for a sleep solution too (not for production code, only for development and tests) and found this article:

JavaScript sleep() or wait()

...and here's another article with client-side solutions: JavaScript sleep

Also, when you are calling alert(), your code will be paused too, while the alert is shown -- you need to find a way to not display alert, but get the same effect. :)

娇女薄笑 2024-07-31 03:26:55

干得好。 正如代码所说,不要成为一个糟糕的开发人员并在网站上使用它。 这是一个开发实用函数。

// Basic sleep function based on ms.
// DO NOT USE ON PUBLIC FACING WEBSITES.
function sleep(ms) {
    var unixtime_ms = new Date().getTime();
    while(new Date().getTime() < unixtime_ms + ms) {}
}

Here you go. As the code says, don't be a bad developer and use this on websites. It's a development utility function.

// Basic sleep function based on ms.
// DO NOT USE ON PUBLIC FACING WEBSITES.
function sleep(ms) {
    var unixtime_ms = new Date().getTime();
    while(new Date().getTime() < unixtime_ms + ms) {}
}
一念一轮回 2024-07-31 03:26:55

这是使用同步 XMLHttpRequest 的简单解决方案:

function sleep(n){
  var request = new XMLHttpRequest();
  request.open('GET', '/sleep.php?n=' + n, false);  // `false` makes the request synchronous
  request.send(null);
}

文件 sleep.php 的内容:

<?php sleep($_GET['n']);

现在使用以下方式调用它:

sleep(5);

使用现有的服务器实现

如果您没有自己的应用程序服务器(对于上述 PHP 脚本) ,您可以使用一些在线服务。 例如:

function sleep(n) { 
    var request = new XMLHttpRequest();
    request.open('GET', 'http://httpstat.us/200?sleep=' + n, false);
    request.send(null);
};

sleep(1000);
console.log("one second delay completed.");

支持

关于为异步参数传递falsemdn 注释:

主线程上的同步请求很容易破坏用户体验,应该避免; 事实上,许多浏览器已经完全弃用了主线程上的同步 XHR 支持。 Workers 中允许同步请求。

实际延迟

作为参数传递的毫秒数将是服务器在接收请求和发送响应之间等待的时间。 由传输和服务器负载引起的延迟将被添加到其中。

Here's a simple solution using a synchronous XMLHttpRequest:

function sleep(n){
  var request = new XMLHttpRequest();
  request.open('GET', '/sleep.php?n=' + n, false);  // `false` makes the request synchronous
  request.send(null);
}

Contents of file sleep.php:

<?php sleep($_GET['n']);

Now call it with:

sleep(5);

Using an existing server implementation

If you don't have your own application server (for the above PHP script), you could use some online service instead. For instance:

function sleep(n) { 
    var request = new XMLHttpRequest();
    request.open('GET', 'http://httpstat.us/200?sleep=' + n, false);
    request.send(null);
};

sleep(1000);
console.log("one second delay completed.");

Support

About passing false for the asynchronous parameter, mdn notes:

Synchronous requests on the main thread can be easily disruptive to the user experience and should be avoided; in fact, many browsers have deprecated synchronous XHR support on the main thread entirely. Synchronous requests are permitted in Workers.

The actual delay

The number of milliseconds that is passed as argument will be the time that the server waits between receiving the request and sending the response. The delay incurred by transmission and server load will be added to that.

灯下孤影 2024-07-31 03:26:55

2019 年更新使用 Atomics.wait

它应该在 Node.js 9.3 或更高版本中工作。

我需要在 Node.js 中使用一个非常准确的计时器,它非常适合这一点。

然而,浏览器的支持似乎极其有限。

let ms = 10000;
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);

运行了一些 10 秒计时器基准测试。

使用 setTimeout 时,我得到的错误高达 7000 微秒(7 毫秒)。

使用 Atomics,我的错误似乎保持在 600 微秒 (0.6 ms)

2020 更新:摘要 以下

function sleep(millis){ // Need help of a server-side page
  let netMillis = Math.max(millis-5, 0); // Assuming 5 ms overhead
  let xhr = new XMLHttpRequest();
  xhr.open('GET', '/sleep.jsp?millis=' + netMillis + '&rand=' + Math.random(), false);
  try{
    xhr.send();
  }catch(e){
  }
}

function sleepAsync(millis){ // Use only in async function
  let netMillis = Math.max(millis-1, 0); // Assuming 1 ms overhead
  return new Promise((resolve) => {
    setTimeout(resolve, netMillis);
  });
}
function sleepSync(millis){ // Use only in worker thread, currently Chrome-only
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, millis);
}

function sleepTest(){
  console.time('sleep');
  sleep(1000);
  console.timeEnd('sleep');
}

async function sleepAsyncTest(){
  console.time('sleepAsync');
  await sleepAsync(1000);
  console.timeEnd('sleepAsync');
}

function sleepSyncTest(){
  let source = `${sleepSync.toString()}
    console.time('sleepSync');
    sleepSync(1000);
    console.timeEnd('sleepSync');`;
  let src = 'data:text/javascript,' + encodeURIComponent(source);
  console.log(src);
  var worker = new Worker(src);
}

,其中服务器端页面(例如 sleep.jsp)看起来喜欢:

<%
try{
  Thread.sleep(Long.parseLong(request.getParameter("millis")));
}catch(InterruptedException e){}
%>

2019 Update using Atomics.wait

It should work in Node.js 9.3 or higher.

I needed a pretty accurate timer in Node.js and it works great for that.

However, it seems like there is extremely limited support in browsers.

let ms = 10000;
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);

Ran a few 10 second timer benchmarks.

With setTimeout I get a error of up to 7000 microseconds (7 ms).

With Atomics, my error seems to stay under 600 microseconds (0.6 ms)

2020 Update: In Summary

function sleep(millis){ // Need help of a server-side page
  let netMillis = Math.max(millis-5, 0); // Assuming 5 ms overhead
  let xhr = new XMLHttpRequest();
  xhr.open('GET', '/sleep.jsp?millis=' + netMillis + '&rand=' + Math.random(), false);
  try{
    xhr.send();
  }catch(e){
  }
}

function sleepAsync(millis){ // Use only in async function
  let netMillis = Math.max(millis-1, 0); // Assuming 1 ms overhead
  return new Promise((resolve) => {
    setTimeout(resolve, netMillis);
  });
}
function sleepSync(millis){ // Use only in worker thread, currently Chrome-only
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, millis);
}

function sleepTest(){
  console.time('sleep');
  sleep(1000);
  console.timeEnd('sleep');
}

async function sleepAsyncTest(){
  console.time('sleepAsync');
  await sleepAsync(1000);
  console.timeEnd('sleepAsync');
}

function sleepSyncTest(){
  let source = `${sleepSync.toString()}
    console.time('sleepSync');
    sleepSync(1000);
    console.timeEnd('sleepSync');`;
  let src = 'data:text/javascript,' + encodeURIComponent(source);
  console.log(src);
  var worker = new Worker(src);
}

of which the server-side page, e.g. sleep.jsp, looks like:

<%
try{
  Thread.sleep(Long.parseLong(request.getParameter("millis")));
}catch(InterruptedException e){}
%>
错爱 2024-07-31 03:26:55

内联:

(async () => await new Promise(resolve => setTimeout(resolve, 500)))();

这里的 500 是 VM 在移动到下一行代码之前等待的时间(以毫秒为单位)。

tldr 的一点;

基本上,当您创建一个 Promise 时,它​​会在创建时返回一个可观察的对象,并在回调中提供解析的引用,以便在数据/响应可用时移交数据/响应。 这里,resolve 在 500ms 后通过 setTimeOut 被调用,直到解析没有被执行,外部作用域才会等待进一步的处理,因此,创建了一个假阻塞。 它与非阻塞(或在其他语言中称为非线程保留睡眠)完全不同,因为线程和很可能的 UI 以及网页/节点应用程序的任何其他正在进行的任务将被阻塞,并且主线程将被阻塞。专门用于等待承诺决议。

An inliner:

(async () => await new Promise(resolve => setTimeout(resolve, 500)))();

500 here is the time in milliseconds for which VM will wait before moving to the next line of code.

Bit of tldr;

Basically, when you create a promise, it returns an observable while at creation giving a reference of resolve in a callback meant for handing over data/response once it's available. Here, resolve is called via setTimeOut after 500ms, and till resolve is not executed the outside scope is waiting to proceed further, hence, creating a fake blocking. It's totally different than the non-blocking(or call non-thread-reserving sleep available in other languages), as the thread and most probably the UI and any other ongoing tasks of webpage/node-application will be blocked and the main thread will be exclusively used for awaiting the promise resolution.

小ぇ时光︴ 2024-07-31 03:26:55

首先:

定义一个要执行的函数,如下所示:

function alertWorld(){
  alert("Hello, World!");
}

然后使用 setTimeout 方法安排其执行:

setTimeout(alertWorld, 1000)

请注意两件事:

  • 第二个参数是以毫秒为单位的时间,
  • 作为第一个参数,您必须仅传递名称函数的(参考),不带括号

First:

Define a function you want to execute like this:

function alertWorld(){
  alert("Hello, World!");
}

Then schedule its execution with the setTimeout method:

setTimeout(alertWorld, 1000)

Note two things

  • the second argument is time in milliseconds
  • as a first argument, you have to pass just the name (reference) of the function, without the parentheses
垂暮老矣 2024-07-31 03:26:55

没有任何依赖的最短解决方案:

await new Promise(resolve => setTimeout(resolve, 5000));

The shortest solution without any dependencies:

await new Promise(resolve => setTimeout(resolve, 5000));
万人眼中万个我 2024-07-31 03:26:55

让事情看起来像大多数人想要的那样的更好的解决方案是使用匿名函数:

alert('start');
var a = 'foo';
// Lots of code
setTimeout(function(){  // Beginning of code that should run AFTER the timeout
    alert(a);
    // Lots more code
}, 5000);  // Put the timeout here

这可能是最接近您想要的功能的东西。

请注意,如果您需要多次睡眠,这可能会很快变得丑陋,您实际上可能需要重新考虑您的设计。

A better solution to make things look like what most people want is to use an anonymous function:

alert('start');
var a = 'foo';
// Lots of code
setTimeout(function(){  // Beginning of code that should run AFTER the timeout
    alert(a);
    // Lots more code
}, 5000);  // Put the timeout here

This is probably the closest you'll get to something that simply does what you want.

Note, if you need multiple sleeps this can get ugly in a hurry and you might actually need to rethink your design.

七堇年 2024-07-31 03:26:55

setTimeout 是 JavaScript 异步方法的一部分(开始执行的方法,其结果将在将来的某个时间排队到称为回调队列的组件,稍后执行)

您可能想要什么要做的就是将 setTimeout 函数包装在 Promise 中。

承诺示例:

const sleep = time => new Promise(res => setTimeout(res, time, "done sleeping"));

// using native promises
sleep(2000).then(msg => console.log(msg));

异步/等待示例:

const sleep = time => new Promise(res => setTimeout(res, time, "done sleeping"));

// using async/await in top level
(async function(){
  const msg = await sleep(2000);
  console.log(msg);
})();

详细了解 setTimeout

The setTimeout is part of the JavaScript asynchronous methods (methods which are starting to execute and their result will be queued sometime in the future to a component called the callback queue, later to be executed)

What you probably want to do is to wrap the setTimeout function within a Promise.

promise example:

const sleep = time => new Promise(res => setTimeout(res, time, "done sleeping"));

// using native promises
sleep(2000).then(msg => console.log(msg));

async/await example:

const sleep = time => new Promise(res => setTimeout(res, time, "done sleeping"));

// using async/await in top level
(async function(){
  const msg = await sleep(2000);
  console.log(msg);
})();

Read more about setTimeout

吃不饱 2024-07-31 03:26:55

一行使用承诺

const wait = t => new Promise(s => setTimeout(s, t, t));

打字稿和中止信号

const wait = (x: number, signal?: AbortSignal): Promise<number> => {
  return new Promise((s, f) => {
    const id = setTimeout(s, x, x);
    signal?.addEventListener('abort', () => {
      clearTimeout(id);
      f('AbortError');
    });
  });
};

演示

const wait = t => new Promise(s => setTimeout(s, t));
// Usage
async function demo() {
    // Count down
    let i = 6;
    while (i--) {
        await wait(1000);
        console.log(i);
    }
    // Sum of numbers 0 to 5 using by delay of 1 second
    const sum = await [...Array(6).keys()].reduce(async (a, b) => {
        a = await a;
        await wait(1000);
        const result = a + b;
        console.log(`${a} + ${b} = ${result}`);
        return result;
    }, Promise.resolve(0));
    console.log("sum", sum);
}
demo();

One-liner using Promises

const wait = t => new Promise(s => setTimeout(s, t, t));

Typescript with Abort Signal

const wait = (x: number, signal?: AbortSignal): Promise<number> => {
  return new Promise((s, f) => {
    const id = setTimeout(s, x, x);
    signal?.addEventListener('abort', () => {
      clearTimeout(id);
      f('AbortError');
    });
  });
};

Demo

const wait = t => new Promise(s => setTimeout(s, t));
// Usage
async function demo() {
    // Count down
    let i = 6;
    while (i--) {
        await wait(1000);
        console.log(i);
    }
    // Sum of numbers 0 to 5 using by delay of 1 second
    const sum = await [...Array(6).keys()].reduce(async (a, b) => {
        a = await a;
        await wait(1000);
        const result = a + b;
        console.log(`${a} + ${b} = ${result}`);
        return result;
    }, Promise.resolve(0));
    console.log("sum", sum);
}
demo();

方觉久 2024-07-31 03:26:55

我会将 setTimeOut 封装在 Promise 中,以实现与其他异步任务的代码一致性: Demo in Fiddle

function sleep(ms)
{
    return(new Promise(function(resolve, reject) {
        setTimeout(function() { resolve(); }, ms);
    }));
}

它的使用方式如下:

sleep(2000).then(function() {
   // Do something
});

如果你习惯使用 Promise,那么语法很容易记住。

I would encapsulate setTimeOut in a Promise for code consistency with other asynchronous tasks: Demo in Fiddle

function sleep(ms)
{
    return(new Promise(function(resolve, reject) {
        setTimeout(function() { resolve(); }, ms);
    }));
}

It is used like this:

sleep(2000).then(function() {
   // Do something
});

It is easy to remember the syntax if you are used to using Promises.

聚集的泪 2024-07-31 03:26:55

此答案适用于 Node 18 及更高版本!

await new Promise(resolve => setTimeout(resolve, 2000));

我们现在可以做

const { setTimeout } = require('timers/promises');
await setTimeout(3000); // sleep 3 seconds

This answer is for Node 18 and newer versions!

Instead of doing:

await new Promise(resolve => setTimeout(resolve, 2000));

We can now do:

const { setTimeout } = require('timers/promises');
await setTimeout(3000); // sleep 3 seconds
心如荒岛 2024-07-31 03:26:55

对于浏览器,我同意 setTimeout 和 setInterval 是可行的方法。

但对于服务器端代码,它可能需要一个阻塞函数(例如,这样您就可以有效地进行线程同步)。

如果您使用 Node.jsMeteor,您可能遇到了在 Fiber 中使用 setTimeout 的限制。 这是服务器端睡眠的代码。

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

请参阅:Node.js Fibers,睡眠

For browsers, I agree that setTimeout and setInterval are the way to go.

But for server-side code, it may require a blocking function (for example, so you can effectively have thread synchronization).

If you're using Node.js and Meteor, you may have run into the limitations of using setTimeout in a fiber. Here is the code for server-side sleep.

var Fiber = require('fibers');

function sleep(ms) {
    var fiber = Fiber.current;
    setTimeout(function() {
        fiber.run();
    }, ms);
    Fiber.yield();
}

Fiber(function() {
    console.log('wait... ' + new Date);
    sleep(1000);
    console.log('ok... ' + new Date);
}).run();
console.log('back in main');

See: Node.js Fibers, Sleep

错々过的事 2024-07-31 03:26:55

这里的大多数答案都是误导的,或者至少是过时的。 JavaScript 没有理由必须是单线程的,事实上也不是。 如今所有主流浏览器都支持worker。 在此之前,其他 JavaScript 运行时(例如 Rhino 和 Node.js 均受支持)多线程。

“JavaScript 是单线程的”不是一个有效的答案。 例如,在工作线程中运行睡眠函数不会阻塞 UI 线程中运行的任何代码。

在支持生成器和yield的较新运行时中,可以为单线程环境中的睡眠函数带来类似的功能:

// This is based on the latest ES6 drafts.
// JavaScript 1.7+ (SpiderMonkey/Firefox 2+) syntax is slightly different

// Run code you want to sleep here (omit star if using JavaScript 1.7)
function* main(){
    for (var i = 0; i < 10; i++) {
        // To sleep for 10 milliseconds 10 times in a row
        yield 10;
    }

    yield 5;
    console.log('I just slept 5 milliseconds!');
}

// Resume the given generator after ms milliseconds
function resume(ms, generator){
    setTimeout(function(){
        // Omit .value if using JavaScript 1.7
        var nextSleep = generator.next().value;
        resume(nextSleep, generator);
    }, ms);
}

// Initialize a generator and get first sleep for the recursive function
var
    generator = main(),
    firstSleep = generator.next().value;

// Initialize recursive resume function
resume(firstSleep, generator);

这种对睡眠的模仿与真正的睡眠函数不同,因为它不会阻塞线程。 它只是 JavaScript 当前 setTimeout 函数之上的糖。 此功能类型已在 Task.js 中实现,现在应该可以在 Firefox 中使用。

Most of the answers here are misguided or at the very least outdated. There is no reason JavaScript has to be single threaded, and indeed it isn't. Today all the mainstream browsers support workers. Before this was the case, other JavaScript runtimes like Rhino and Node.js supported multithreading.

'JavaScript is single threaded' is not a valid answer. For example, running a sleep function within a worker would not block any of the code running in the UI thread.

In newer runtimes supporting generators and yield, one could bring similar functionality to the sleep function in a singlethreaded environment:

// This is based on the latest ES6 drafts.
// JavaScript 1.7+ (SpiderMonkey/Firefox 2+) syntax is slightly different

// Run code you want to sleep here (omit star if using JavaScript 1.7)
function* main(){
    for (var i = 0; i < 10; i++) {
        // To sleep for 10 milliseconds 10 times in a row
        yield 10;
    }

    yield 5;
    console.log('I just slept 5 milliseconds!');
}

// Resume the given generator after ms milliseconds
function resume(ms, generator){
    setTimeout(function(){
        // Omit .value if using JavaScript 1.7
        var nextSleep = generator.next().value;
        resume(nextSleep, generator);
    }, ms);
}

// Initialize a generator and get first sleep for the recursive function
var
    generator = main(),
    firstSleep = generator.next().value;

// Initialize recursive resume function
resume(firstSleep, generator);

This imitation of sleep is different from a true sleep function as it does not block the thread. It is simply sugar on top of JavaScript's current setTimeout function. This functionality type has been implemented in Task.js and should work today in Firefox.

心欲静而疯不止 2024-07-31 03:26:55

更新 2022

只需使用此代码片段即可。

await new Promise(resolve => setTimeout(resolve, 2000));

UPDATE 2022

Just use this code snippet.

await new Promise(resolve => setTimeout(resolve, 2000));
ι不睡觉的鱼゛ 2024-07-31 03:26:55

Node.js 7.6 起,您可以结合 utils 模块中的 >promisify 函数带有 setTimeout

const sleep = require('util').promisify(setTimeout)

一般用法

async function main() {
    console.time("Slept for")
    await sleep(3000)
    console.timeEnd("Slept for")
}

main()

问题 用法

async function asyncGenerator() {
    while (goOn) {
      var fileList = await listFiles(nextPageToken);
      await sleep(3000)
      var parents = await requestParents(fileList);
    }
  }

Since Node.js 7.6, you can combine the promisify function from the utils module with setTimeout.

const sleep = require('util').promisify(setTimeout)

General Usage

async function main() {
    console.time("Slept for")
    await sleep(3000)
    console.timeEnd("Slept for")
}

main()

Question Usage

async function asyncGenerator() {
    while (goOn) {
      var fileList = await listFiles(nextPageToken);
      await sleep(3000)
      var parents = await requestParents(fileList);
    }
  }
末骤雨初歇 2024-07-31 03:26:55

我已经搜索/谷歌搜索了相当多关于 JavaScript 睡眠/等待的网页...如果您希望 JavaScript“运行、延迟、运行”,则没有答案...大多数人得到的要么是,“RUN,RUN(无用的东西),RUN”或“RUN,RUN +延迟RUN”......

我想:
这是一个有效的解决方案......但是你必须砍掉正在运行的代码......:
是的,我知道,这只是一个更容易阅读的重构...仍然...

示例 1:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setInterval
var i = 0;

function run() {
    // Pieces of codes to run
    if (i == 0){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i == 1){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i == 2){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i >2){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i == 5){document.getElementById("id1").innerHTML= "<p>all code segment finished running</p>"; clearInterval(t); } // End interval, stops run
    i++; // Segment of code finished running, next...
}

run();
t = setInterval("run()", 1000);

</script>
</body>
</html>

示例 2:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setTimeout
var i = 0;

function run() {
    // Pieces of codes to run, can use switch statement
    if (i == 0){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>"; sleep(1000);}
    if (i == 1){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>"; sleep(2000);}
    if (i == 2){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>"; sleep(3000);}
    if (i == 3){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>";} //stops automatically
    i++;
}

function sleep(dur) {t=setTimeout("run()", dur);} // Starts flow control again after 'dur'

run(); // Starts
</script>
</body>
</html>

示例 3:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setTimeout
var i = 0;

function flow() {
    run(i);
    i++; // Code segment finished running, increment i; can put elsewhere
    sleep(1000);
    if (i == 5) {clearTimeout(t);} // Stops flow, must be after sleep()
}

function run(segment) {
    // Pieces of codes to run, can use switch statement
    if (segment == 0){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 1){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 2){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
}

function sleep(dur) {t=setTimeout("flow()", dur);} // Starts flow control again after 'dur'

flow(); // Starts flow
</script>
</body>
</html>

示例 4:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setTimeout, switch
var i = 0;

function flow() {
    switch(i)
    {
        case 0:
            run(i);
            sleep(1000);
            break;
        case 1:
            run(i);
            sleep(2000);
            break;
        case 5:
            run(i);
            clearTimeout(t); // Stops flow
            break;
        default:
            run(i);
            sleep(3000);
            break;
    }
}

function run(segment) {
    // Pieces of codes to run, can use switch statement
    if (segment == 0){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 1){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 2){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    i++; // Current segment of code finished running, next...
}

function sleep(dur) {t=setTimeout("flow()", dur);} // Starts flow control again after 'dur'

flow(); // Starts flow control for first time...
</script>
</body>
</html>

I have searched/googled quite a few webpages on JavaScript sleep/wait... and there is no answer if you want JavaScript to "RUN, DELAY, RUN"... what most people got was either, "RUN, RUN(useless stuff), RUN" or "RUN, RUN + delayed RUN"...

I thought:
here is a solution that works... but you have to chop up your running codes...:
Yes, I know, this is just an easier to read refactoring... still...

Example 1:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setInterval
var i = 0;

function run() {
    // Pieces of codes to run
    if (i == 0){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i == 1){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i == 2){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i >2){document.getElementById("id1").innerHTML= "<p>code segment " + i + " is ran</p>"; }
    if (i == 5){document.getElementById("id1").innerHTML= "<p>all code segment finished running</p>"; clearInterval(t); } // End interval, stops run
    i++; // Segment of code finished running, next...
}

run();
t = setInterval("run()", 1000);

</script>
</body>
</html>

Example 2:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setTimeout
var i = 0;

function run() {
    // Pieces of codes to run, can use switch statement
    if (i == 0){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>"; sleep(1000);}
    if (i == 1){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>"; sleep(2000);}
    if (i == 2){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>"; sleep(3000);}
    if (i == 3){document.getElementById("id1").innerHTML= "<p>code segment " + i + " ran</p>";} //stops automatically
    i++;
}

function sleep(dur) {t=setTimeout("run()", dur);} // Starts flow control again after 'dur'

run(); // Starts
</script>
</body>
</html>

Example 3:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setTimeout
var i = 0;

function flow() {
    run(i);
    i++; // Code segment finished running, increment i; can put elsewhere
    sleep(1000);
    if (i == 5) {clearTimeout(t);} // Stops flow, must be after sleep()
}

function run(segment) {
    // Pieces of codes to run, can use switch statement
    if (segment == 0){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 1){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 2){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment "+ segment +" is ran</p>"; }
}

function sleep(dur) {t=setTimeout("flow()", dur);} // Starts flow control again after 'dur'

flow(); // Starts flow
</script>
</body>
</html>

Example 4:

<html>
<body>
<div id="id1">DISPLAY</div>

<script>
// JavaScript sleep by "therealdealsince1982"; copyrighted 2009
// setTimeout, switch
var i = 0;

function flow() {
    switch(i)
    {
        case 0:
            run(i);
            sleep(1000);
            break;
        case 1:
            run(i);
            sleep(2000);
            break;
        case 5:
            run(i);
            clearTimeout(t); // Stops flow
            break;
        default:
            run(i);
            sleep(3000);
            break;
    }
}

function run(segment) {
    // Pieces of codes to run, can use switch statement
    if (segment == 0){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 1){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment == 2){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    if (segment >2){document.getElementById("id1").innerHTML= "<p>code segment " + segment + " is ran</p>"; }
    i++; // Current segment of code finished running, next...
}

function sleep(dur) {t=setTimeout("flow()", dur);} // Starts flow control again after 'dur'

flow(); // Starts flow control for first time...
</script>
</body>
</html>
空心↖ 2024-07-31 03:26:55
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
独孤求败 2024-07-31 03:26:55

如果您想要比 setTimeoutsetInterval 更简洁的函数,您可以将它们包装在仅颠倒参数顺序的函数中,并给它们起个好听的名字:

function after(ms, fn){ setTimeout(fn, ms); }
function every(ms, fn){ setInterval(fn, ms); }

CoffeeScript 版本:

after = (ms, fn)-> setTimeout fn, ms
every = (ms, fn)-> setInterval fn, ms

然后您可以将它们与匿名函数很好地结合使用:

after(1000, function(){
    console.log("it's been a second");
    after(1000, function(){
        console.log("it's been another second");
    });
});

现在它很容易读作“N 毫秒后,.. .”(或“每 N 毫秒,...”)

If you want less clunky functions than setTimeout and setInterval, you can wrap them in functions that just reverse the order of the arguments and give them nice names:

function after(ms, fn){ setTimeout(fn, ms); }
function every(ms, fn){ setInterval(fn, ms); }

CoffeeScript versions:

after = (ms, fn)-> setTimeout fn, ms
every = (ms, fn)-> setInterval fn, ms

You can then use them nicely with anonymous functions:

after(1000, function(){
    console.log("it's been a second");
    after(1000, function(){
        console.log("it's been another second");
    });
});

Now it reads easily as "after N milliseconds, ..." (or "every N milliseconds, ...")

你与昨日 2024-07-31 03:26:55

如果您必须处理同步执行,我可以理解睡眠函数的用途。 setInterval 和 setTimeout 函数创建一个并行执行线程,它将执行序列返回给主程序,如果您必须等待给定结果,则该线程是无效的。 当然,我们可以使用事件和处理程序,但在某些情况下这并不是我们想要的。

I can understand the purpose of a sleep function if you have to deal with synchronous execution. The setInterval and setTimeout functions create a parallel execution thread which returns the execution sequence back to the main program, which is ineffective if you have to wait for a given result. Of course one may use events and handlers, but in some cases is not what is intended.

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