我怎么能在Node.js(Javascript)中等待,我需要暂停一段时间

Chr*_*len 322 javascript yield node.js

我正在为个人需求开发类似脚本的控制台.我需要能够暂停一段时间,但是,根据我的研究,node.js无法按要求停止.经过一段时间后很难读取用户的信息......我已经看到了一些代码,但我相信他们必须在其中包含其他代码才能使其工作,例如:

setTimeout(function() {
}, 3000);
Run Code Online (Sandbox Code Playgroud)

但是,在这段代码之后,我需要在一段时间后执行所有内容.

例如,

//start-of-code
console.log('Welcome to My Console,');
some-wait-code-here-for-ten-seconds..........
console.log('Blah blah blah blah extra-blah');
//endcode. 
Run Code Online (Sandbox Code Playgroud)

我也看过像

yield sleep(2000);
Run Code Online (Sandbox Code Playgroud)

但node.js不承认这一点.

我怎样才能实现这种延长的暂停?

Ami*_*ein 334

对旧问题的新答案.今天(2017年1月)它更容易.您可以使用async/await语法.例如:

async function init(){
   console.log(1)
   await sleep(1000)
   console.log(2)
}
function sleep(ms){
    return new Promise(resolve=>{
        setTimeout(resolve,ms)
    })
}
Run Code Online (Sandbox Code Playgroud)

async/await在没有安装和插件的情况下使用开箱即可,您必须使用--harmony标志来使用node-v7或node-v8 .

更多信息:

  • `let sleep = ms => new Promise(resolve => setTimeout(resolve,ms));`对于像我这样的oneliner怪胎:) (31认同)
  • 让sleep = require('util')。promisify(setTimeout);在Node 7.6+上工作并提高可读性 (11认同)
  • 这真的应该是答案,sleep node.js包可能很麻烦. (6认同)
  • 我想你忘记了`sleep(1000)`前面的`await`关键字 (5认同)
  • 最好的解决方案 (4认同)
  • 这今天拯救了我的培根(特别是 @BrianHVB 发布的“promisify”食谱)。 (2认同)
  • 这是一个很好的答案,因为它总结了多年来的不同方法。请考虑使用“timers/promises”中的“setTimeout”在顶部进行另一个更新。请参阅@maxim-orlov 的答案,该答案远低于([链接](/sf/answers/5000980141/)) (2认同)

Ell*_*lle 190

最好的方法是将代码分解为多个函数,如下所示:

function function1() {
    // stuff you want to happen right away
    console.log('Welcome to My Console,');
}

function function2() {
    // all the stuff you want to happen after that pause
    console.log('Blah blah blah blah extra-blah');
}

// call the first chunk of code right away
function1();

// call the rest of the code and have it execute after 3 seconds
setTimeout(function2, 3000);
Run Code Online (Sandbox Code Playgroud)

它与JohnnyHK的解决方案类似,但更简洁,更容易扩展.

  • @ CyrilDuchon-Doris什么? (7认同)
  • @LucasSeveryn那时你做错了.这是一种核心设计模式. (6认同)
  • 使用@ machineghost的答案来获得一个优雅的基于promise的解决方案,该解决方案不需要自定义代码并支持await/async (3认同)
  • 这对ECMA6来说会很好看:`setTimeout(()=> {},3000)` (2认同)

Joh*_*yHK 141

setTimeout回调中放置延迟后要执行的代码:

console.log('Welcome to My Console,');
setTimeout(function() {
    console.log('Blah blah blah blah extra-blah');
}, 3000);
Run Code Online (Sandbox Code Playgroud)

  • @ElliotBonneville这只是一个例子来说明这个概念.显然,您可以(应该)将代码分解为函数调用,而不是使用内联代码,就像其他任何地方一样. (32认同)
  • 这是非常麻烦的做法,通常是不好的做法,尤其是在OP希望在延迟之后运行程序的其余部分时。看我的答案。 (2认同)

atl*_*ex2 127

这是一种简单的阻塞技术:

var waitTill = new Date(new Date().getTime() + seconds * 1000);
while(waitTill > new Date()){}
Run Code Online (Sandbox Code Playgroud)

只要脚本中没有其他任何内容(如回调),它就会阻塞.但由于这是一个控制台脚本,也许这就是你需要的!

  • 太可怕了.但它的确有效.没有回调.回调地狱是一件真实的事情.当代码已经充满回调时,我用这个来对api的响应进行单元测试. (24认同)
  • 可怕与否,它做了一个简单的`等待',它阻止它,它适用于某些测试目的.正是我在寻找什么. (22认同)
  • 这是一个"旋转等待". (11认同)
  • @Ali似乎是目标. (6认同)
  • 完美地回答没有第三方库的问题,并且很简单.然而人们说"可怕"....这很好,例如模拟繁重的CPU负载等.顺便说一下这个https://www.phpied.com/sleep-in-javascript/ (5认同)
  • 这是该问题的唯一正确答案。OP 特别要求调用等待函数,从该函数返回,然后继续。(没有回调,没有异步任何东西,没有重写整个调用堆栈来处理承诺。)唯一完全符合OP想要的解决方案是调用外部程序,例如Windows上的“SLEEP.EXE”。 (5认同)
  • @codebeat 如果您正在等待,它实际上没有任何区别。这就是旋转部分! (4认同)
  • 这会严重影响 CPU 周期 (3认同)
  • 这对 CPU 的消耗速度与 V8 允许什么都不做一样快 (3认同)
  • 如果您尝试模拟会减慢事件循环速度的东西,从而也会减慢其他用户/连接的速度,这也是必需的方法。添加延迟回调不会影响其他用户/连接。 (2认同)
  • 这是最糟糕的睡眠方式,它会阻塞主节点线程! (2认同)
  • 精彩的回答! (2认同)

k06*_*06a 94

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

await new Promise(resolve => setTimeout(resolve, 5000));
Run Code Online (Sandbox Code Playgroud)

  • "复杂的高度是简单." - Clare Booth Luce.这是迄今为止最好的答案,IMO. (6认同)
  • `let sleep = require('util')。promisify(setTimeout);`长三个字符,但可重用并且更易读imo (4认同)
  • 这显然比其他答案更新近,但它是2018年最优雅的,它可以在一行中完成工作而不会对代码产生任何其他影响. (3认同)
  • 为了避免 eslint 投诉,请将其称为“resolve”而不是“done”。即 `await new Promise(resolve => setTimeout(resolve, 5000))` (2认同)

Max*_*lov 67

从 Node.js 15 及更高版本开始,您可以使用Timers Promises API。您不必再承诺setTimeout或依赖第三方库。

import { setTimeout } from 'node:timers/promises';

await setTimeout(1000);
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的解决方案 - 请不要写下自己的承诺。 (4认同)

Luc*_*iva 59

使用现代Javascript简单而优雅的睡眠功能

function sleep(millis) {
    return new Promise(resolve => setTimeout(resolve, millis));
}
Run Code Online (Sandbox Code Playgroud)

没有依赖,没有回调地狱; 而已 :-)


考虑到问题中给出的示例,这就是我们在两个控制台日志之间休眠的方式:

async function main() {
    console.log("Foo");
    await sleep(2000);
    console.log("Bar");
}

main();
Run Code Online (Sandbox Code Playgroud)

"缺点"是你的主要功能现在也必须async如此.但是,考虑到你已经在编写现代Javascript代码,你可能(或者至少应该是!)使用async/ await遍布你的代码,所以这真的不是问题.今天所有现代浏览器都支持它.

给人一种小洞察sleep一点用都没有为这些功能async/await和脂肪箭头运营商,这是写它的详细方式:

function sleep(millis) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () { resolve(); }, millis);
    });
}
Run Code Online (Sandbox Code Playgroud)

但是,使用胖箭头操作符可以使它更小(更优雅).

  • 我喜欢在我的脚本中使用以下单行:`const sleep = ms => new Promise(resolve => setTimeout(resolve,ms));; (8认同)

Rya*_*ton 51

在节点7.6.0或更高版本上

Node支持本机等待:

const sleep = (waitTimeInMs) => new Promise(resolve => setTimeout(resolve, waitTimeInMs));
Run Code Online (Sandbox Code Playgroud)

那么如果你可以使用异步函数:

await sleep(10000); // sleep for 10 seconds
Run Code Online (Sandbox Code Playgroud)

要么:

sleep(10000).then(() => {
  // This will execute 10 seconds from now
});
Run Code Online (Sandbox Code Playgroud)

在较旧的Node版本上(原始答案)

我想要一个在Windows和Linux中运行的异步睡眠,而不需要长时间占用我的CPU.我试过睡眠包但它不会安装在我的Windows机器上.我最终使用:

https://www.npmjs.com/package/system-sleep

要安装它,请键入:

npm install system-sleep
Run Code Online (Sandbox Code Playgroud)

在你的代码中,

var sleep = require('system-sleep');
sleep(10*1000); // sleep for 10 seconds
Run Code Online (Sandbox Code Playgroud)

奇迹般有效.

  • 很好的答案谢谢 - 它使一些不可能的代码成为可能 - 这不是旋转等待 (2认同)
  • 这个包不能在 Mac OS 上运行,因此不能交叉兼容,因此不可用。见 https://github.com/jochemstoel/nodejs-system-sleep/issues/4 (2认同)
  • 这个应该更高。精彩的答案 (2认同)

Ale*_*sej 47

您可以使用此www.npmjs.com/package/sleep

var sleep = require('sleep');
sleep.sleep(10); // sleep for ten seconds
Run Code Online (Sandbox Code Playgroud)

  • 它在'MacOS`上工作正常,但由于[node_gyp errors](https://github.com/erikdubbelboer/node-sleep/issues/23),它在`CentOS`上遇到错误.它似乎不便携. (2认同)
  • 也许问题不是由操作系统引起的,而是由节点构建引起的 (2认同)

jma*_*777 34

这个问题已经很老了,但最近V8增加了发电机,它可以完成OP要求的功能.在诸如suspendgen-run之类的库的帮助下,生成器通常最容易用于异步交互.

这是一个使用suspend的例子:

suspend(function* () {
    console.log('Welcome to My Console,');
    yield setTimeout(suspend.resume(), 10000); // 10 seconds pass..
    console.log('Blah blah blah blah extra-blah');
})();
Run Code Online (Sandbox Code Playgroud)

相关阅读(通过无耻的自我推销):与发电机有什么关系?.

  • 很好的答案 - 但应该读`yield setTimeout(suspend.resume(),10000);` (2认同)

小智 30

尝试使用 Promise,它在 NodeJS 中对我有用

一班轮

await new Promise(resolve => setTimeout(resolve, 5000));
Run Code Online (Sandbox Code Playgroud)

NodeJS或者将其作为重复使用的函数

const sleep = async (milliseconds) => {
    await new Promise(resolve => setTimeout(resolve, milliseconds));
}
Run Code Online (Sandbox Code Playgroud)

使用像这样的函数

await sleep(5000)
Run Code Online (Sandbox Code Playgroud)


Mar*_*lva 19

Node 16有一种新方法可以轻松做到这一点

import { setTimeout } from 'timers/promises'

console.log('before')
await setTimeout(3000)
console.log('after')
Run Code Online (Sandbox Code Playgroud)


小智 17

在Linux/nodejs上,这对我有用:

const spawnSync = require('child_process').spawnSync;

var sleep = spawnSync('sleep',[1.5]);

它是阻塞的,但它不是一个繁忙的等待循环.

您指定的时间以秒为单位,但可以是一小部分.我不知道其他操作系统是否有类似的命令.


mac*_*ost 15

如果你想"编码高尔夫",你可以在这里做一些其他答案的缩短版本:

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
Run Code Online (Sandbox Code Playgroud)

但在我看来,真正理想的答案是使用Node的util库及其promisify功能,它正是为这类东西而设计的(基于承诺的以前存在的基于非承诺的东西版本):

const util = require('util');
const sleep = util.promisify(setTimeout);
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下,您都可以通过使用await调用sleep函数暂停:

await sleep(1000); // sleep for 1s/1000ms
Run Code Online (Sandbox Code Playgroud)

  • @Fabian,如果你只需要一次:`await require('util').promisify(setTimeout)(1000);` (2认同)

Luc*_*ato 13

我最近创建了一个名为wait.for的简单抽象来在同步模式下调用异步函数(基于节点光纤).还有一个基于即将推出的ES6发电机的版本.

https://github.com/luciotato/waitfor

使用wait.for,您可以调用任何标准nodejs async函数,就像它是同步函数一样,不会阻塞节点的事件循环.

您可以在需要时按顺序编码,这是(我猜测)完美的简化脚本供个人使用.

使用wait.for您的代码将是:

require('waitfor')

..in a fiber..
//start-of-code
console.log('Welcome to My Console,');
wait.miliseconds(10*1000); //defined in waitfor/paralell-tests.js - DOES NOT BLOCK
console.log('Blah blah blah blah extra-blah');
//endcode. 
Run Code Online (Sandbox Code Playgroud)

也可以在同步模式下调用任何异步功能.检查示例.

  • 在我从`wait.for/paralell-tests.js`获得它之后,我遇到了与未定义属性等相关的另一个错误.所以我也需要复制它们.为什么不以不需要的方式组织代码? (2认同)

HIL*_*EEN 7

因为,javascript引擎(v8)基于事件队列中的事件序列运行代码,没有严格的javascript在指定时间之后准确触发执行.也就是说,当您稍后设置几秒钟来执行代码时,触发代码完全基于事件队列中的序列.因此,触发代码执行可能需要超过指定的时间.

所以Node.js如下,

process.nextTick()
Run Code Online (Sandbox Code Playgroud)

稍后运行代码而不是setTimeout().例如,

process.nextTick(function(){
    console.log("This will be printed later");
});
Run Code Online (Sandbox Code Playgroud)