Как мне ждать в Node.js (JavaScript)? Мне нужно сделать паузу на время

Разрабатываю консольный скрипт для личных нужд. Мне нужно иметь возможность делать паузу на продолжительное время, но, судя по моим исследованиям, 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 этого не распознает.

Как мне добиться этой продолжительной паузы?


person Christopher Allen    schedule 10.01.2013    source источник
comment
@Christopher Allen, может быть, не имеет отношения к делу, но выполняет свою работу: require("child_process").execSync('php -r "sleep($argv[1]);" ' + seconds);   -  person Haitham Sweilem    schedule 04.01.2016
comment
Модуль npm node-sleep может помочь (однако я бы использовал его только для отладки )   -  person Julian Soro    schedule 19.02.2016
comment
Отвечает ли это на ваш вопрос? Что такое версия sleep () для JavaScript?   -  person Dan Dascalescu    schedule 24.05.2021


Ответы (24)


Обновление от января 2021 г.: вы даже можете сделать это в интерактивном режиме 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 июнь 2019) все намного проще. Вы можете использовать новый синтаксис 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 г.. Используя последние версии NodeJS, вы можете использовать его прямо из коробки. Не нужно указывать аргументы командной строки. Даже Google Chrome поддерживает его сегодня.

Обновление, май 2020 г .: Скоро вы сможете использовать синтаксис await вне асинхронной функции. На верхнем уровне, как в этом примере

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

Предложение находится на этапе 3. Вы можете использовать его сегодня, используя webpack 5 (альфа),

Дополнительная информация:

person Aminadav Glickshtein    schedule 31.01.2017
comment
Я думаю, вы забыли ключевое слово await перед sleep(1000) - person Ryan Jarvis; 13.03.2017
comment
Это действительно должно быть ответом, пакет sleep node.js может вызвать проблемы. - person Stuart Allen; 20.12.2017
comment
let sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); Для одинарных уродов вроде меня :) - person Predrag Stojadinović; 30.05.2018
comment
let sleep = require('util').promisify(setTimeout); работает на Node 7.6+ и улучшает читаемость - person BrianHVB; 07.05.2019
comment
Это спасло мой сегодня бекон (в частности, promisify рецепт, опубликованный @BrianHVB). - person kindall; 15.05.2019
comment
Это отлично работает для меня, использовал его как RateLimiter для приложения. - person meanbunny; 06.10.2019
comment
Обратите внимание: если вы используете это внутри цикла, это не сработает, если вы выполняете x.forEach. Вместо этого вам придется использовать современный цикл for ... of, как подробно описано в этом ответе: stackoverflow.com/questions/37576685/ - person Navid Khan; 20.01.2021

Кратчайшее решение без зависимостей:

await new Promise(resolve => setTimeout(resolve, 5000));
person k06a    schedule 06.03.2018
comment
Вершина изысканности - простота. - Клэр Бут Люс. Это, безусловно, лучший ответ, ИМО. - person arnold; 28.06.2018
comment
Это, очевидно, намного позже, чем другие ответы, но это самый элегантный по состоянию на 2018 год, когда работа выполняется в 1 строке без каких-либо других воздействий на код. - person Herick; 03.12.2018
comment
Это хороший. Однако вы должны использовать NodeJS 7.6.0 или выше. Это не будет работать в более старых версиях. - person Ryan Shillington; 31.12.2018
comment
let sleep = require('util').promisify(setTimeout); на три символа длиннее, но многоразовый и более читаемый imo - person BrianHVB; 07.05.2019
comment
действительно просто, но я предпочитаю поместить это в более читаемый режим сна. Таким образом становится ясно, что делает линия. ваше здоровье! - person gone43v3r; 16.07.2019
comment
Чтобы избежать жалобы на eslint, назовите его resolve вместо done. Т.е. await new Promise(resolve => setTimeout(resolve, 5000)) - person Darren Cook; 02.11.2019

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

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, но намного проще и проще в расширении.

person Elliot Bonneville    schedule 10.01.2013
comment
@LucasSeveryn Значит, ты что-то делаешь не так. Это основной шаблон проектирования. - person Elliot Bonneville; 09.06.2015
comment
И что вы делаете, когда запуск функции находится не на расстоянии одной функции, а на расстоянии 10 файлов от кода, который необходимо деасинхронизировать? - person Cyril Duchon-Doris; 28.06.2016
comment
@ CyrilDuchon-Doris Что? - person AturSams; 03.05.2017
comment
используйте ответ @ machineghost для элегантного решения на основе обещаний, которое не требует специального кода и поддерживает await / async - person Dane Macaulay; 27.11.2017
comment
Это асинхронный режим, это означает, что если функция function1 завершается раньше, чем через 3 секунды, они начинают перекрывать друг друга. Тогда вы даже не сможете вернуться, и его почти никогда не использовать. Единственный способ, который я нашел до сих пор, - использовать debugger; - person Cristian Traìna; 17.08.2018

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

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

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

person atlex2    schedule 01.06.2016
comment
ужасно это или нет, но он просто делает wait, блокирует и работает для некоторой тестовой цели. Именно то, что я искал. - person Clijsters; 10.07.2016
comment
отлично отвечает на вопрос без сторонних библиотек и просто. Но люди говорят ужасно .... Это здорово, например. для имитации большой загрузки процессора и т. д. Кстати, очень похоже на этот phpied.com/sleep-in-javascript - person Don Cheadle; 06.02.2017
comment
Также это обязательный подход, если вы пытаетесь смоделировать что-то, что замедлит цикл событий, тем самым замедляя и других пользователей / соединения. Добавление отложенных обратных вызовов не повлияет на других пользователей / соединения. - person Don Cheadle; 06.02.2017
comment
Это spin-wait. - person Mike Atlas; 29.03.2017
comment
Это худший способ засыпания, он блокирует поток основного узла! - person Ali; 07.02.2018
comment
@Ali, похоже, это цель. - person Félix Adriyel Gagnon-Grenier; 21.03.2018
comment
это безумие, это все блокирует - person datdinhquoc; 23.08.2018
comment
Это сборщик процессора и потребляет память, лучше повторно использовать объект даты, а не каждый раз создавать новый. - person Codebeat; 24.09.2018
comment
@codebeat На самом деле нет никакой разницы, если вы ждете вращения. Это часть вращения! - person atlex2; 27.09.2018
comment
Блестящий ответ! - person nurgasemetey; 15.12.2018
comment
Ах да, давайте заполним весь ЦП сервера и заблокируем поток узла. Лучшее решение на свете; также должны быть размещены на ShittyCode. - person Daniele Orlando; 16.10.2019
comment
Это сильно влияет на цикл процессора. - person JVK; 17.04.2020
comment
Это единственно правильный ответ на вопрос. OP специально попросил вызвать функцию ожидания, вернуться из функции и продолжить. (Никаких обратных вызовов, никаких асинхронных операций, никакой перезаписи всего стека вызовов для обработки обещаний.) Единственное другое решение, которое делает именно то, что хотел OP, - это вызов внешней программы, например SLEEP.EXE в Windows. - person blitter; 22.04.2020
comment
Лучший ответ!! Должно быть наверху. - person Bhavya Gupta; 19.10.2020

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

console.log('Welcome to My Console,');
setTimeout(function() {
    console.log('Blah blah blah blah extra-blah');
}, 3000);
person JohnnyHK    schedule 10.01.2013
comment
Это ужасно беспорядочно и, как правило, плохая практика, особенно если OP хочет, чтобы остальная часть программы запускалась после этой задержки. Смотрите мой ответ. - person Elliot Bonneville; 10.01.2013
comment
@ElliotBonneville Это просто пример для иллюстрации концепции. Очевидно, вы могли (должны) преобразовать код в вызов функции вместо использования встроенного кода, как и в любом другом месте. - person JohnnyHK; 10.01.2013
comment
@ChristopherKemp: Оказывается, в Node.js есть решение под названием node-fibers. Оцените. - person Elliot Bonneville; 10.01.2013
comment
Это отличное решение, особенно если вы не хотите выполнять какой-либо код, вы просто хотите имитировать метод сна внутри цикла. В этом примере нет ничего плохого. - person Halfstop; 25.10.2016
comment
это идеально подходит для задержки запросов, поступающих от клиента, я использовал этот подход, чтобы протестировать свои загрузочные счетчики на стороне клиента - person moein rahimi; 24.12.2017

На узле 7.6.0 или выше

Node изначально поддерживает ожидание:

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

тогда, если вы можете использовать асинхронные функции:

await sleep(10000); // sleep for 10 seconds

or:

sleep(10000).then(() => {
  // This will execute 10 seconds from now
});

В старых версиях Node (исходный ответ)

Мне нужен асинхронный сон, который работал бы в Windows и Linux, не перегружая мой процессор долгим циклом while. Я попробовал спящий пакет, но он не установился на моем компьютере с Windows. В итоге я использовал:

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

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

npm install system-sleep

В вашем коде

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

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

person Ryan Shillington    schedule 13.01.2017
comment
отличный ответ, спасибо - он сделал возможным невозможный код - это НЕ ожидание спина - person danday74; 10.09.2017
comment
При дальнейших исследованиях этот модуль полагается на deasync, который разветвляется из другого deasync-репозитория github. Исходное репо предупреждает не использовать его, так как это взлом. Он работает, но не на всех платформах, поэтому, если вам нужно кроссплатформенное решение, избегайте этого. - person danday74; 11.09.2017
comment
Это странно. Мы успешно используем его как в Linux, так и в Windows. Какая ОС не работает? - person Ryan Shillington; 07.03.2018
comment
рассматривает проблемы в репозитории github system-sleep, и нет никакой гарантии, что это будет работать в будущем - проверьте код system-sleep, чтобы узнать, какой модуль он использует под капотом, затем посмотрите на модуль, который был разветвлен, и предупреждение данный - person danday74; 07.03.2018
comment
Похоже, здесь находится его единственная зависимость: github.com/jakwuh/deasync-promise. Я не вижу ничего плохого в этом проекте и никаких предупреждений. У меня не тот проект? - person Ryan Shillington; 08.03.2018
comment
зависимость system-sleep - это deasync-prom, зависимость deasync - а deasync - это форк github.com/vkurchatkin/ deasync - вы не можете засыпать основной поток, не взломав его в узле - это то, что делает deasync - person danday74; 08.03.2018
comment
да, я никогда не сталкивался с проблемами, и это отлично подходит для разработчиков - под капотом я считаю, что он полагается на C или C ++, который широко доступен, но я думаю, на некоторых машинах его нет, и тогда он терпит неудачу, поэтому он вызывает проблемы - в случае сбоя системный сон возвращается к циклическому ожиданию, которое приостанавливает выполнение кода - person danday74; 08.03.2018
comment
Этот пакет не работает в Mac OS и, следовательно, не является кросс-совместимым и, следовательно, не работает. См. github.com/jochemstoel/nodejs-system-sleep/issues/4 - person nuzzolilo; 29.12.2018
comment
@Nuzzolilo Это странно. У нас есть один разработчик Mac OS, и он никогда не упоминал ничего плохого. Я подозреваю, что это конкретная версия Mac OS. Я также обновил этот ответ, поскольку сон в основном встроен в новые версии NodeJS. - person Ryan Shillington; 31.12.2018
comment
@ user8385393 Если вы используете узел 12.18.2, вы должны использовать раздел On Node 7.6.0 or higher. - person Ryan Shillington; 15.09.2020
comment
Проголосовали за оригинальный ответ - person panta82; 13.12.2020
comment
Это должно быть выше. Блестящий ответ - person dz210; 04.06.2021

Простая и элегантная функция сна с использованием современного 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, вы, вероятно (или, по крайней мере, должны использовать!), Используете _4 _ / _ 5_ во всем своем коде, так что это действительно не проблема. Все современные браузеры сегодня поддерживают его.

Чтобы немного разобраться в функции sleep для тех, кто не привык к async/await и операторам жирной стрелки, вот подробный способ ее написания:

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

Однако использование оператора жирной стрелки делает его еще меньше (и более элегантным).

person Lucio Paiva    schedule 13.10.2017
comment
Вы также можете написать функцию сна без async и оставить все остальное без изменений. С async, наверное, яснее. - person Kevin Peña; 27.10.2017
comment
Хороший улов, @ KevinPeña. На самом деле, я думаю, что предпочитаю это без async. Отредактировал свой ответ своим предложением. Я не думаю, что это делает код более понятным; для этого я бы прибегнул к JSDoc. - person Lucio Paiva; 29.10.2017
comment
Мне нравится, когда мои скрипты однострочные: const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); - person korya; 23.01.2018

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

var sleep = require('sleep');
sleep.sleep(10); // sleep for ten seconds
person Aleksej    schedule 22.04.2016
comment
Он отлично работает на MacOS, но обнаруживает ошибки на CentOS из-за ошибок node_gyp . Вроде не переносной. - person AechoLiu; 11.08.2017
comment
возможно проблема вызвана не ОС, а сборкой узла - person Aleksej; 07.10.2017

Это довольно старый вопрос, но недавно V8 добавил генераторы, которые могут выполнять то, что запрашивал OP. Генераторы, как правило, проще всего использовать для асинхронного взаимодействия с помощью такой библиотеки, как suspend или gen-run.

Вот пример использования приостановки:

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

Чтение по теме (в порядке бессовестной саморекламы): В чем дело с генераторами? .

person jmar777    schedule 21.08.2013
comment
Хороший ответ - но следует прочитать yield setTimeout(suspend.resume(), 10000); - person edhubbell; 22.04.2015
comment
Спасибо, @edhubbell. Этот ответ был основан на очень старой версии приостановки, но вы правы относительно последней. Я обновлю ответ. - person jmar777; 23.04.2015
comment
для какой версии узла это? - person danday74; 10.09.2017
comment
@ danday74 Я не могу точно вспомнить, когда они не были помечены, но они существуют с v0.12 за флагом --harmony, и, согласно node.green, они, по крайней мере, доступны без каких-либо флагов, начиная с v4.8.4 : node.green/#ES2015-functions-generators-basic-functionality . Однако обратите внимание, что новый синтаксис async/await обеспечивает лучшее решение этой проблемы, без необходимости в дополнительных библиотеках, таких как suspend. См. Пример в этом ответе: stackoverflow.com/a/41957152/376789. Асинхронные функции доступны (без флагов) начиная с версии 7.10. - person jmar777; 12.09.2017
comment
Это очень сложно по состоянию на 2021 год. - person Dan Dascalescu; 24.05.2021

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

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

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

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

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

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

РЕДАКТИРОВАТЬ: Как отмечалось в комментариях, вы даже можете сократить это до одной строки:

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

Или, если вы даже не хотите беспокоиться о создании sleep функции:

await require('util').promisify(setTimeout)(1000);
person machineghost    schedule 24.10.2017
comment
На самом деле, используя util.promisify, невозможно вызвать сон без предоставления обратного вызова. nodejs.org/api/ - person Howie; 18.12.2017
comment
Вам не хватает await. Он как бы создает обратный вызов, приостанавливает работу, а затем перезапускает код, когда этот обратный вызов возвращается. Обратный вызов возвращается со значением, но в данном случае нас это не волнует, поэтому слева от await нет ничего. - person machineghost; 18.12.2017
comment
напишите его в одну строку, чтобы винить код гольф;) const sleep = require ('util'). promisify (setTimeout); - person Fabian; 04.01.2019
comment
@Fabian, а если понадобится только один раз: await require('util').promisify(setTimeout)(1000); - person Ed'ka; 26.09.2020

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

const spawnSync = требуется ('дочерний_процесс'). spawnSync;

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

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

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

person Bart Verheijen    schedule 18.11.2016
comment
sleep в значительной степени вездесущ и полезен с первых дней UNIX en.wikipedia.org/wiki / Sleep_% 28Unix% 29. Только не редкая ОС, которая может не существовать, - это окна (однако там вы можете попробовать child_process.spawnSync('timeout', ['/T', '10']) - person humanityANDpeace; 24.10.2018

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

https://github.com/luciotato/waitfor

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

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

используя 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. 

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

person Lucio M. Tato    schedule 06.09.2013
comment
комментарий гласит: // определено в waitfor / paralell-tests.js, возьмите его из этого файла. - person Lucio M. Tato; 14.03.2014
comment
после того, как я получил его от wait.for/paralell-tests.js, я столкнулся с другой ошибкой, связанной с неопределенными свойствами и т. д. Поэтому мне нужно было скопировать и их. Почему бы вам не организовать код таким образом, чтобы этого не требовалось? - person Dmitry Koroliov; 27.03.2014
comment
Wait.for и другие оптоволоконные решения открыли для меня совершенно новый мир! Если бы я мог, я бы проголосовал за это миллион раз. Хотя большая часть сообщества nodejs выступает против волокон, я думаю, что они являются фантастическим дополнением и определенно имеют свое место, когда дело доходит до ада обратных вызовов. - person Levi Roberts; 24.05.2014

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

Итак, Node.js следует,

process.nextTick()

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

process.nextTick(function(){
    console.log("This will be printed later");
});
person HILARUDEEN S ALLAUDEEN    schedule 10.01.2013

Поскольку 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);
};

Обратите внимание, что функция doWhat становится обратным вызовом resolve в new Promise(...).

Также обратите внимание, что это АСИНХРОННЫЙ сон. Он не блокирует цикл событий. Если вам нужно заблокировать сон, используйте эту библиотеку, которая реализует блокировку сна с помощью привязок C ++. (Хотя необходимость в блокирующем режиме сна в Node-подобных асинхронных средах возникает редко.)

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

person treecoder    schedule 18.05.2017

Попробуйте использовать обещание, у меня это работает в NodeJS

один лайнер

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

или использовать его как функцию в NodeJS для повторного использования

const sleep = async (milliseconds) => {
    await new Promise(resolve => setTimeout(resolve, milliseconds));
}

используйте функцию типа

await sleep(5000)
person Abdul Gaffar    schedule 10.06.2021

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. Чтобы полностью понять, как это работает, необходимо полностью понять, как работает генератор. Ключевое слово function, за которым следует *, в современном Javascript называется функцией генератора. Пакет npm co предоставляет функцию runner для запуска генератора.

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

person Qian Chen    schedule 08.03.2017
comment
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа. - person Donald Duck; 08.03.2017
comment
Спасибо @DonaldDuck. Код в моем ответе, вероятно, является самой захватывающей частью улучшения Javascript. Я так поражен, что некоторые супер-умные люди думают об этом способе решения проблемы ада обратного вызова. - person Qian Chen; 08.03.2017

Это модуль со вкусом moment.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;
person Boaz - CorporateShillExchange    schedule 08.11.2017

просто, мы собираемся подождать 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;
        }
    })();
person Stan Sokolov    schedule 22.03.2017

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

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

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

person Dazt    schedule 13.04.2017

function doThen(conditional,then,timer) {
    var timer = timer || 1;
    var interval = setInterval(function(){
        if(conditional()) {
            clearInterval(interval);
            then();
        }
    }, timer);
}

Пример использования:

var counter = 1;
doThen(
    function() {
        counter++;
        return counter == 1000;
    },
    function() {
        console.log("Counter hit 1000"); // 1000 repeats later
    }
)
person Chris Hemmens    schedule 24.06.2020

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

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
person Ivan Talalaev    schedule 29.11.2016

Другие ответы хороши, но я подумал, что выберу другой такт.

Если все, что вам действительно нужно, это замедлить работу определенного файла в 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 говорит, что вывод не буферизируется.

person Pete    schedule 13.03.2017

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

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

Для получения дополнительной информации о

yield sleep(2000); 

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

person Arseni Buinitski    schedule 09.09.2016