我正在为个人需求开发一个控制台脚本。我需要能够暂停更长的时间,但是,根据我的研究,Node.js没有办法根据需要停止。一段时间后,读取用户信息变得越来越困难了……我已经看到了一些代码,但我相信他们必须有其他的代码在他们的工作,如:

    setTimeout(function() {
    }, 3000);

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

例如,

    // start of code
    console.log('Welcome to my console,');

    some-wait-code-here-for-ten-seconds...

    console.log('Blah blah blah blah extra-blah');
    // end of code

我还见过

    yield sleep(2000);

但是Node.js不能识别这个。

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


当前回答

为了在javascript中“等待”,使用承诺是一种方法,正如上面的答案所示。

那么如何使用它呢?

下面是一个简单的例子,一个5秒的子进程以非阻塞的方式为一个4秒的主进程排队参数。

const wait = (seconds) => 
    new Promise(resolve => 
        setTimeout(() => 
            resolve(true), seconds * 1000))

const process = async (items, prepTask, mainTask) => {
    const queue = [];
    let done = false;

    items.forEach((item, i) => {
        prepTask(item).then(() => {
            queue.push(item);
            if (i == items.length -1) {
                done = true;
            }
        })
    })

    while (!done || queue.length) {
        if (queue.length) {
            const workload = queue.shift();
            await mainTask(workload)
        } else {
            console.log('waiting for subtask to queue')
            await wait(1);
        }
    }
}

// Usage Example

const ids = [1,2,3,4,5,6,7,8,9,10];

const prepTask = async (id) => {
    await wait(id * 5)
    return id * 5;
}

const mainTask = async (workload) => {
    console.log('excuting workload: ', workload);
    const result = await wait(4);
    return { workload, result }
}

process(ids, prepTask, mainTask)
    .then(() => console.log('done'))

其他回答

将你想要在延迟后执行的代码放在setTimeout回调函数中:

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

我最近创建了一个更简单的抽象概念,叫做等待。用于在同步模式下调用异步函数(基于节点光纤)。还有一个基于即将到来的ES6生成器的版本。

https://github.com/luciotato/waitfor

使用等。对于,你可以调用任何标准的nodejs async函数,就像它是一个同步函数一样,而不会阻塞node的事件循环。

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

使用等。你的代码将是:

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. 

同样,任何async函数都可以在Sync模式下调用。 检查例子。

使用现代Javascript的简单而优雅的睡眠函数

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

没有依赖,没有回调;就是这样:-)


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

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

main();

“缺点”是你的主函数现在也必须是异步的。但是,考虑到您已经在编写现代Javascript代码,您可能(或者至少应该!)在所有代码中使用async/await,所以这真的不是一个问题。现在所有的浏览器都支持它。

对于那些不习惯async/await和胖箭头操作符的人,稍微深入了解一下sleep函数,下面是详细的书写方式:

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

但是,使用胖箭头操作符会使它更小(也更优雅)。

有了ES6支持的promise,我们可以在没有任何第三方帮助的情况下使用它们。

const sleep = (seconds) => {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, (seconds * 1000));
    });
};

// We are not using `reject` anywhere, but it is good to
// stick to standard signature.

然后这样使用它:

const waitThenDo(howLong, doWhat) => {
    return sleep(howLong).then(doWhat);
};

注意,doWhat函数变成了新的Promise(…)中的解析回调函数。

还要注意,这是异步睡眠。它不会阻塞事件循环。如果你需要阻塞睡眠,使用这个库,它在c++绑定的帮助下实现了阻塞睡眠。(尽管在Node中像异步环境一样需要阻塞睡眠的情况很少。)

https://github.com/erikdubbelboer/node-sleep

2021年1月更新:你甚至可以在Node REPL交互中使用——experimental-repl-await标志来实现

$ node --experimental-repl-await
> const delay = ms => new Promise(resolve => setTimeout(resolve, ms))
> await delay(1000) /// waiting 1 second.

老问题的新答案。今天(2017年1月至2019年6月)要容易得多。您可以使用新的async/await语法。 例如:

async function init() {
  console.log(1);
  await sleep(1000);
  console.log(2);
}

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

为了在不安装插件的情况下使用async/await,你必须使用node-v7或node-v8,并使用——harmony标志。

2019年6月更新:通过使用最新版本的NodeJS,您可以开箱即用。不需要提供命令行参数。即使谷歌Chrome今天也支持它。

2020年5月更新: 很快你就可以在async函数之外使用await语法了。在顶层,比如这个例子

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

提案已进入第三阶段。 今天你可以通过webpack 5 (alpha)使用它,

更多信息:

Nodejs中的和谐标志:https://nodejs.org/en/docs/es6/ 所有NodeJS版本下载:https://nodejs.org/en/download/releases/