Как Я Могу Ждать В Узле.js (Javascript), l нужно сделать паузу на некоторое время

Я разрабатываю консоль, как скрипт для личных нужд... Мне нужно иметь возможность приостанавливаться на длительное время, но как узел.js из моих исследований не может остановиться, как требуется.... Его становится трудно читать информацию пользователей после определенного периода времени... iv видел какой-то код там, но я считаю, что у них должны быть другие коды внутри них, чтобы они работали, такие как:

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');
//endcode. 

Я видел такие вещи, как

yield sleep(2000);

но узел.js не распознает этого....

Если кто-то готов помочь, это очень ценится.

23 ответов


лучший способ сделать это-разбить код на несколько функций, например:

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);

это похоже на JohnnyHKрешение, но гораздо аккуратнее и легче расширить.


вставляете код, который вы хотите выполнить после задержки в элементе setTimeout обратного вызова:

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

новый ответ на старый вопрос. Сегодня (январь 2017) это намного проще. Вы можете использовать новая 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 флаг.

Подробнее:


Это простой метод блокирования:

var waitTill = new Date(new Date().getTime() + seconds * 1000);
while(waitTill > new Date()){}

Это блокировка поскольку в вашем скрипте больше ничего не произойдет (например, обратные вызовы). Но поскольку это консольный скрипт, возможно, это то, что вам нужно!


вы можете использовать это www.npmjs.com/package/sleep

var sleep = require('sleep');
sleep.sleep(10); // sleep for ten seconds

этот вопрос довольно старый, но недавно V8 добавил генераторы, которые могут выполнить то, что запросил OP. Генераторы обычно проще всего использовать для асинхронных взаимодействий с помощью библиотеки, такой как приостановить или gen-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');
})();

связанное чтение (путем бесстыдного продвижения себя):в чем проблема с генераторами?.


простая и элегантная функция сна с использованием современного Javascript

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

нет зависимостей, нет обратного вызова ада; вот и все : -)


учитывая пример, приведенный в вопросе, вот как мы будем ждать между двумя журналами консоли:

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

main();

"недостатком" является то, что ваша основная функция должна быть async как хорошо. Но, учитывая, что вы уже пишете современный код Javascript, вы должны использовать async/await по всему вашему коду, так что это действительно не проблема. Все современные браузеры сегодня поддержка его.

даем немного понять


кратчайшее решение без каких-либо зависимостей:

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

недавно я создал более простую абстракцию под названием подождать.для для вызова асинхронных функций в режиме синхронизации (на основе узла-волокон). Существует также версия, основанная на предстоящих генераторах ES6.

https://github.com/luciotato/waitfor

С помощью подождать.для, вы можете вызвать любую стандартную асинхронную функцию nodejs, как если бы это была функция синхронизации, без блокировки цикла событий узла.

вы можете кодировать последовательно, когда вам нужно он, который (я предполагаю) идеально подходит для упрощения ваших сценариев для личного использования.

С помощью подождать.для ваш код будет:

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. 

также любую асинхронную функцию можно вызвать в синхронизация режим. Проверьте примеры.


в Linux/nodejs это работает для меня:

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

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

он блокирует, но это не занятый цикл ожидания.

время указывается в секундах, но может быть дробным. Я не знаю, есть ли у других ОС аналогичная команда.


Я хотел асинхронный сон, который работал в Windows & Linux, без засорения моего процессора длительным циклом. Я попробовал пакет сна, но он не будет установлен на моем окне Windows. Я закончил использовать:

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

чтобы установить его, введите:

npm install system-sleep

в коде

var sleep = require('system-sleep');
sleep(10*1000); // sleep for 10 seconds

работает как шарм.


если вы хотите "код гольф" вы можете сделать более короткую версию некоторых других ответов здесь:

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

но на самом деле идеальным ответом, на мой взгляд, является использование узла util и promisify функция, которая предназначена именно для такого рода вещей (создание основанных на обещаниях версий ранее существующих вещей, не основанных на обещаниях):

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

в любом случае вы можете сделать паузу, просто используя await для вызова sleep функция:

await sleep(1000); // sleep for 1s/1000ms

поскольку JavaScript engine (v8) запускает код на основе последовательности событий в очереди событий, нет строгого правила, что javascript точно запускает выполнение после указанного времени. То есть, когда вы задаете несколько секунд для выполнения кода позже, код запуска является чисто базовым по последовательности в очереди событий. Таким образом, запуск выполнения кода может занять больше времени, чем указано.

So Узел.js следует,

process.nextTick()

для запуска кода позже вместо setTimeout (). Для пример,

process.nextTick(function(){
    console.log("This will be printed later");
});

С ES6 в поддержку Promises, мы можем использовать их без помощи третьих лиц.

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);
};

отметим, что становится resolve обратный вызов в пределах new Promise(...).

также обратите внимание, что это асинхронный сон. Он не блокирует цикл событий. Если вам нужна блокировка сна, используйте эту библиотеку, которая реализует блокировку сна с помощью привязок C++. (Хотя необходимость блокировки сна в узле, как асинхронные среды встречаются редко.)

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


let co = require('co');
const sleep = ms => new Promise(res => setTimeout(res, ms));

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

этот код выше является побочным эффектом решения проблемы асинхронного обратного вызова Javascript. Это также причина, по которой я думаю, что делает Javascript полезным языком в бэкэнде. На самом деле это самое захватывающее улучшение, введенное в современный Javascript, на мой взгляд. Чтобы полностью понять, как это работает, как работает генератор, необходимо полностью понять. The function ключевое слово, за которым следует * называется функцией генератора в современном Javascript. Пакет npm co предусмотрена функция runner для запуска генератора.

по существу функция генератора предоставила способ приостановить выполнение функции с yield ключевое слово, в то же время, yield в функции генератора, что позволило обмениваться информацией между внутри генератора и вызывающего абонента. Это обеспечило механизм для вызывающего абонента для извлечения данных из promise из асинхронного вызова и передать разрешенные данные обратно в генератор. Эффектно, оно делает асинхронный вызов синхронный.


Если вам просто нужно приостановить для тестирования цели выполнения текущего потока попробуйте следующее:

function longExecFunc(callback, count) {

    for (var j = 0; j < count; j++) {
        for (var i = 1; i < (1 << 30); i++) {
            var q = Math.sqrt(1 << 30);
        }
    }
    callback();
}
longExecFunc(() => { console.log('done!')}, 5); //5, 6 ... whatever. Higher -- longer

simple мы будем ждать 5 секунд для некоторого события, чтобы произойти (это будет указано переменной done, установленной в true где-то еще в коде) или когда тайм-аут истекает, что мы будем проверять каждые 100 мс

    var timeout=5000; //will wait for 5 seconds or untildone
    var scope = this; //bind this to scope variable
    (function() {
        if (timeout<=0 || scope.done) //timeout expired or done
        {
            scope.callback();//some function to call after we are done
        }
        else
        {
            setTimeout(arguments.callee,100) //call itself again until done
            timeout -= 100;
        }
    })();

для некоторых людей принятый ответ не работает, я нашел этот другой ответ, и он работает для меня:Как передать параметр в обратный вызов setTimeout ()?

var hello = "Hello World";
setTimeout(alert, 1000, hello); 

'hello' - передаваемый параметр, вы можете передать все параметры после времени ожидания. Спасибо @Fabio Phms за ответ.


посмотрите на readline-sync (https://www.npmjs.com/package/readline-sync)

установить с npm install readline-sync

var readlineSync = require('readline-sync');
while(true) {
  var input = readlineSync.question("What is your input?");
  if(input === 'exit') {
    process.exit();
  } else {
    console.log("Your input was " + input);
  }
}

может быть, не лучшая практика, но делает работу для меня


этот момент.JS ароматизированный модуль на основе грязный блокирующий подход, предложенный @atlex2. использовать это только для тестирования.

const moment = require('moment');

let sleep = (secondsToSleep = 1) => {
    let sleepUntill = moment().add(secondsToSleep, 'seconds');
    while(moment().isBefore(sleepUntill)) { /* block the process */ }
}

module.exports = sleep;

другие ответы отличные, но я решил взять другой подход.

Если все, что вы действительно ищете, это замедлить определенный файл в linux:

 rm slowfile; mkfifo slowfile; perl -e 'select STDOUT; $| = 1; while(<>) {print $_; sleep(1) if (($ii++ % 5) == 0); }' myfile > slowfile  &

узел myprog slowfile

Это будет спать 1 сек каждые пять строк. Программа узла будет работать так же медленно, как и писатель. Если он делает другие вещи, они будут на нормальной скорости.

mkfifo создает первый-в-первый-из трубы. Это то, что заставляет это работать. Строки в Perl будешь писать так быстро, как захочешь. $/=1 говорит, что не буферизует вывод.


подробнее о

yield sleep(2000); 

вы должны проверить Redux-Saga. Но это специфично для вашего выбора Redux в качестве вашей модели (хотя строго не обязательно).


Я собрал, прочитав ответы в этом вопросе, простую функцию, которая также может выполнить обратный вызов, если вам это нужно:

function waitFor(ms, cb) {
  var waitTill = new Date(new Date().getTime() + ms);
  while(waitTill > new Date()){};
  if (cb) {
    cb()
  } else {
   return true
  }
}