Что такое JavaScript-версия sleep ()?

1716

Есть ли лучший способ для разработки sleep в JavaScript, чем следующая функция pausecomp (взята здесь)?

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

Это не дубликат Sleep in JavaScript - задержка между действиями; Мне нужен настоящий сон в середине функции, а не задержка перед выполнением кода.

  • 3
    Это должно быть установлено в середине времени, если я использую setTimeout, то while будет продолжать обрабатывать и ставить в очередь больше setTimeout, которые в конечном итоге будут выполняться в одно и то же время, и между ними будет немного параллелизма.
  • 124
    Это ужасное решение - вы будете жевать циклы обработки, ничего не делая.
Показать ещё 2 комментария
Теги:
sleep

72 ответа

1568
Лучший ответ

Обновление 2017

С 2009 года, когда был задан этот вопрос, JavaScript значительно эволюционировал. Все остальные ответы сейчас устарели или слишком сложны. Вот текущая лучшая практика:

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

async function demo() {
  console.log('Taking a break...');
  await sleep(2000);
  console.log('Two seconds later');
}

demo();

Это оно. await sleep(<duration>).

Вы можете попробовать этот код в прямом эфире на Runkit. Обратите внимание, что,

  1. await может выполняться только в функциях с префиксом с ключевым словом async. Runkit оборачивает ваш код в асинхронную функцию перед его выполнением.
  2. await только приостанавливает текущую async функцию

Две новые функции JavaScript помогли написать настоящую функцию "сна":

Совместимость

Если по какой-либо причине вы используете Node старше 7 лет или нацелены на старые браузеры, async/await все еще можно использовать через Babel (инструмент, который перенесет JavaScript + новые функции в обычный старый JavaScript) с помощью transform-async-to-generator плагин transform-async-to-generator. Бежать

npm install babel-cli --save

Создайте .babelrc с:

{
  "plugins": [
    "transform-async-to-generator",
  ]
}

Затем запустите свой код с

node_modules/babel-cli/bin/babel-node.js sleep.js

Но опять же, вам это не нужно, если вы используете Node 7 или более позднюю версию или если вы ориентируетесь на современные браузеры.

  • 3
    Отличный материал здесь. Интересно, как это влияет или связано с «активными» / «неактивными» состояниями современных браузеров после того, как JS вызывает «спящий» режим? Может ли браузер блокировать спящий режим, как и ожидалось для обычного JS, чтобы позже вызывать его, когда он становится «активным», или у него другое поведение?
  • 13
    Какова текущая поддержка браузера для этого? Я бы не считал предыдущие решения «устаревшими», пока это решение не поддерживается подавляющим большинством браузеров или, по крайней мере, всеми распространенными. Наоборот, я бы посчитал это решение интересным, но непригодным / непрактичным, пока оно не получит широкую поддержку.
Показать ещё 14 комментариев
797

(см. обновленный ответ на 2016 год)

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

Проблема здесь в том, что JavaScript является однопоточной моделью на основе событий. Хотя в конкретном случае было бы неплохо заставить весь двигатель ждать несколько секунд, в общем, это плохая практика. Предположим, я хотел использовать ваши функции при написании собственных? Когда я позвоню вашему методу, мои методы все замерзнут. Если бы JavaScript мог каким-то образом сохранить контекст выполнения функции, сохраните ее где-нибудь, затем верните ее и продолжите позже, тогда может произойти сон, но в основном это будет threading.

Итак, вы сильно зацикливаетесь на том, что предложили другие, вам нужно разбить код на несколько функций.

Тогда ваш вопрос немного ложный. Невозможно спать так, как вы хотите, и не следует предлагать решение, которое вы предлагаете.

  • 31
    Это не правильный ответ вообще. Если Javascript не имеет функции сна, это только потому, что ECMAScript не требует этого. Это выбор дизайна органом, ответственным за дизайн Javascript. Можно было бы предположить, что время выполнения Javascript ждет заданный промежуток времени перед запуском следующей строки кода, но было решено не делать этого.
  • 5
    Сон может быть прекрасно реализован в JavaScript, но не с точностью в реальном времени. Ведь это система событий. Если асинхронные вызовы завершены, событие инициируется. Я не вижу причин, по которым то же самое невозможно сделать, когда выдается sleep (), после чего управление возвращается браузеру до тех пор, пока оно не закончится, возвращая управление вызывающей функции. И да, я также согласен с тем, что иногда сон удобен, особенно когда разработчики ДО того, как вы испортили дизайн так сильно, что у вас нет другого выхода, кроме полного рефакторинга, на который у вас нет времени
Показать ещё 4 комментария
614

В JavaScript я переписываю каждую функцию так, чтобы она могла завершиться как можно скорее. Вы хотите, чтобы браузер снова контролировался, чтобы он мог внести изменения в DOM.

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

Я собираюсь отредактировать этот ответ, потому что нашел это полезным:

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

Запись функции сна просто и делает ее еще более пригодной для использования с 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!
});
  • 1
    это решение не работает, если у вас есть переменные состояния. Если функция, которую вы пытаетесь уснуть, имеет какие-либо параметры. Например, как можно сделать fuction foobar (el) {setTimeout (foobar_cont (el), 5000); } ??? Я еще не понял это.
  • 187
    В порядке закрытия. function foobar(el) { setTimeout(function() { foobar_cont(el); }, 5000); }
Показать ещё 23 комментария
296

Только для debug/dev, я отправляю его, если он кому-то полезен

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

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

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

function sleepThenAct(){ sleepFor(2000); console.log("hello js sleep !"); }
  • 28
    Это не ответ. Это точно так же, как код в вопросе, за исключением чуть короче.
Показать ещё 10 комментариев
163

Я согласен с другими плакатами, занятый сон - всего лишь плохая идея.

Однако setTimeout не выполняет выполнение, он выполняет следующую строку функции сразу же после истечения таймаута SET, а не после истечения таймаута, так что не выполняет ту же задачу, что и сон.

Способ сделать это - разбивать вашу функцию на до и после частей.

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

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

Убедитесь, что имена ваших функций по-прежнему точно описывают, что делает каждая часть (I.E.GatherInputThenWait и CheckInput, а не funcPart1 и funcPart2)

Изменить

Этот метод позволяет не выполнять строки кода, который вы решаете, до ПОСЛЕ вашего таймаута, все еще возвращая управление обратно на клиентский ПК, чтобы выполнить все, что он поставил в очередь.

Дальнейшее редактирование

Как указано в комментариях, это абсолютно НЕ РАБОТАЕТ в цикле. Вы могли бы сделать какой-то причудливый (уродливый) взлом, чтобы заставить его работать в цикле, но в целом это будет просто сделать для катастрофического кода спагетти.

  • 11
    Да уж. Это становится сложным, когда у вас есть цикл или даже вложенный цикл. Вы должны отказаться от своих циклов for и иметь вместо них счетчики.
  • 0
    Туш. Я имею в виду, это все еще возможно, но в этом случае уродливо и хакерски. Вы также можете использовать некоторые статические переменные логического состояния, но это тоже довольно хакерски.
Показать ещё 8 комментариев
117

Я знаю, что это немного старый вопрос, но если (например, я) вы используете 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.
   */
}
  • 3
    Это вызов Java?
  • 0
    Да, вызов в спящий поток Java.
Показать ещё 2 комментария
112

Для любви к $DEITY, пожалуйста, не выполняйте функцию ожидания оживленного ожидания. setTimeout и setInterval делать все, что вам нужно.

  • 9
    Согласен. Разве настоящий "сон" не заморозил бы весь движок JavaScript ...
  • 3
    Ну, не совсем все: setInterval производит намного лучшее впечатление от опроса.
Показать ещё 12 комментариев
69

Если вы используете jQuery, кто-то действительно создал плагин "delay", который не более чем обертка для 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');
  • 4
    Это не плохое решение. Сохраняет контекст и цепочность.
  • 37
    Начиная с jQuery 1.4, .delay() является частью jQuery (хотя с семантикой, отличной от описанной выше реализации). api.jquery.com/delay
Показать ещё 2 комментария
41

Я тоже искал решение для сна (не для производственного кода, только для dev/tests) и нашел эту статью:

http://narayanraman.blogspot.com/2005/12/javascript-sleep-or-wait.html

... и еще одна ссылка с клиентскими решениями: http://www.devcheater.com/

Кроме того, когда вы вызываете alert(), ваш код также будет приостановлен, пока отображается предупреждение - нужно найти способ не отображать предупреждение, но получить тот же эффект.:)

  • 32
    Я согласен, многие люди говорят: «Нет, не делайте этого в рабочем коде!» Да, я не хочу. Я хочу сделать это в одноразовом тестовом коде, и в результате я не хочу тратить много времени на создание элегантного решения.
29

Здесь вы идете. Как говорится в коде, не плохой разработчик и используйте это на сайтах. Это функция утилиты разработки.

// 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) {}
}
  • 15
    Это в основном то же самое, что и ОП.
  • 3
    Чтобы быть более точным, это то, что ОП попросил АЛЬТЕРНАТИВУ.
Показать ещё 1 комментарий
24

Здесь простое решение с использованием синхронного 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']);

Теперь вызовите его с помощью: сна (5);

  • 46
    Я предполагаю, что это шутка ... +1!
  • 5
    @lukad, используйте setTimeout() если это работает, но если это означает, что нужно развернуть 1000 строк обратных вызовов, это может начать выглядеть не шуткой.
Показать ещё 3 комментария
18

Мне лично нравится просто:

function sleep(seconds){
    var waitUntil = new Date().getTime() + seconds*1000;
    while(new Date().getTime() < waitUntil) true;
}

то

sleep(2); // Sleeps for 2 seconds

Я все время использую его для создания фальшивого времени загрузки при создании скриптов в P5js

  • 3
    Я рассматриваю это как наиболее оптимизированную версию основного вопроса: он не выполняет никаких математических операций внутри цикла, а представляет собой простое сравнение. Это немного трудно читать, хотя.
  • 0
    НИКОГДА НЕ ДЕЛАЙТЕ ЭТОГО. Вы проверили использование процессора, пока эта функция работает? Он должен быть близок к 100%, если вы уделите ему достаточно времени.
Показать ещё 2 комментария
18

Во-первых:

Определите функцию, которую вы хотите выполнить следующим образом:

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

Затем запланируйте его выполнение с помощью метода setTimeout:

setTimeout(alertWorld,1000)

Обратите внимание на две вещи

  • вторым аргументом является время в миллисекундах.
  • в качестве первого аргумента вам нужно передать только имя (ссылку) функции без скобок
14

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

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

Скорее всего, это ближе всего к тому, что просто делает то, что вы хотите.

Обратите внимание, что если вам нужно много спальных мест, это может стать уродливым в спешке, и вам может потребоваться переосмыслить ваш дизайн.

  • 3
    Это сначала делает pouse, а затем выполняет код.
10

Я бы инкапсулировал setTimeOut в Согласие на совместимость кода с другими асинхронными задачами: Демо в Fiddle

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

Используется следующим образом:

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

Легко запомнить синтаксис, если вы использовали Promises.

  • 3
    Почему это лучше, чем просто использовать setTimeout (function () {/ * сделать что-то * /}, 2000) ;?
9

Большинство ответов здесь ошибочны или, по крайней мере, устарели. Нет никакой причины, по которой javascript должен быть однопоточным, и действительно, это не так. Сегодня все основные браузеры поддерживают рабочих, прежде чем это было связано с другими процессами работы с javascript, такими как Rhino и Node.js, поддерживающими многопоточность.

'Javascript is single threaded' недействительный ответ. Например, запуск функции сна внутри рабочего не будет блокировать какой-либо код, запущенный в потоке ui.

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

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

// run code you want to sleep here (ommit star if using js 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(){
        // ommit .value if using js 1.7
        var nextSleep = generator.next().value;
        resume(nextSleep, generator);
    }, ms);
}

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

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

Эта имитация сна отличается от истинной функции сна, поскольку она не блокирует поток. Это просто сахара поверх функции setTimeout javascript current. Этот тип функциональности был реализован в Task.js и должен работать сегодня в Firefox.

  • 0
    Рабочие не реализованы в IE, по крайней мере, до версии 10. Который в настоящее время представляет большое количество пользователей.
  • 0
    Правда, и даже тогда не практично реализовывать sleep с использованием нескольких работников. При использовании Node.js функции генератора уже реализованы и могут использоваться как описано. Основные браузеры не все реализованные генераторы на сегодняшний день.
9

Для браузеров я согласен, что setTimeout и setInterval - это путь.

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

Если вы используете node.js и метеор, вы можете столкнуться с ограничениями использования 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');

Смотрите: https://github.com/laverdet/node-fibers#sleep

8
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
  • 0
    Это так же, как реальный вопрос. Не имеет особого смысла делать это реальным ответом.
  • 1
    Не очень хорошее решение - с помощью этого в Selenium JavaScriptExecutor примерно 50% времени зависает мой браузер Chrome на 2104 MacBook Pro.
8

Я искал /googled несколько веб-страниц в javascript sleep/wait... и нет ответа, если вы хотите, чтобы javascript "RUN, DELAY, RUN"... то, что большинство людей получили, было либо: "RUN, RUN (бесполезный материал), RUN" или "RUN, RUN + delayed RUN"....

Итак, я съел некоторые гамбургеры и подумал: вот решение, которое работает... но вы должны расколоть свои текущие коды...: да, я знаю, это просто легче читать рефакторинг... еще...

//......................................... //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>

//................. example3:

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

//.............. Example4:

<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>
  • 4
    Хорошо, это работает с setTimeput, но трудно увидеть, что происходит. Использование самого setTimeout проще, чем это.
6

Многие ответы не отвечают на вопрос (и не отвечают), и никто не делает этого...

Здесь мои два цента (или функции):

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

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 been a second");
    after(1000, function(){
        console.log("it been another second");
    });
});

Теперь он легко читается как "после N миллисекунд,..." (или "каждые N миллисекунд,..." )

6

Это можно сделать с помощью метода Java sleep. Я тестировал его в FF и IE, и он не блокирует компьютер, не переваривает ресурсы и не вызывает бесконечных ударов сервера. Кажется, это чистое решение для меня.

Сначала вам нужно загрузить Java на страницу и сделать ее методы доступными. Для этого я сделал следующее:

<html>
<head>

<script type="text/javascript">

  function load() {
    var appletRef = document.getElementById("app");
    window.java = appletRef.Packages.java;
  } // endfunction

</script>

<body onLoad="load()">

<embed id="app" code="java.applet.Applet" type="application/x-java-applet" MAYSCRIPT="true" width="0" height="0" />

Затем все, что вам нужно сделать, когда вам нужна безболезненная пауза в вашем JS:

java.lang.Thread.sleep(xxx)

Где xxx - время в миллисекундах. В моем случае (в порядке обоснования) это было частью выполнения резервного копирования в очень маленькой компании, и мне нужно было распечатать счет, который должен был быть загружен с сервера. Я сделал это, загрузив счет-фактуру (как веб-страницу) в iFrame, а затем распечатав iFrame. Конечно, мне пришлось ждать, пока страница будет полностью загружена, прежде чем я смогу напечатать, поэтому JS пришлось приостановить. Я выполнил это, указав на странице счета (в iFrame) поле скрытой формы на родительской странице с событием onLoad. И код на родительской странице, чтобы распечатать счет-фактуру, выглядел следующим образом (нерелевантные части вырезаны для ясности):

var isReady = eval('document.batchForm.ready');
isReady.value=0;

frames['rpc_frame'].location.href=url;

while (isReady.value==0) {
  java.lang.Thread.sleep(250);
} // endwhile

window.frames['rpc_frame'].focus();
window.frames['rpc_frame'].print();

Таким образом, пользователь нажимает кнопку, script загружает страницу счета-фактуры, а затем ждет, проверяя каждую четверть секунды, чтобы увидеть, завершена ли страница счета-фактуры, затем отобразите диалоговое окно печати, чтобы пользователь мог отправить его на принтер. Что и требовалось доказать.

  • 12
    Кажется довольно чудовищным, если рассмотреть простую вещь, которую хотел достичь автор.
  • 2
    Это зависит от Java-апплетов, которые устарели.
6

Добавление двух моих битов. Мне нужно было ожидание для тестирования. Я не хотел разрывать код, так как это было бы большой работой, поэтому для меня это было просто.

for (var i=0;i<1000000;i++){                    
     //waiting
  }

Я не вижу недостатка в этом, и это помогло мне.

  • 0
    Это может быть скомпилировано.
  • 0
    Пожалуйста, не делай так. Это блокирующий неактивный вызов, что означает, что никакой другой javascript не может быть запущен, пока ваш код перегружает поток JS.
Показать ещё 4 комментария
6

Я могу понять цель функции сна, если вам приходится иметь дело с синхронным исполнением. Функции setInterval и setTimeout создают поток параллельного выполнения, который возвращает последовательность выполнения обратно в основную программу, что неэффективно, если вам нужно ждать определенного результата. Конечно, можно использовать события и обработчики, но в некоторых случаях это не то, что предполагается.

6

Один сценарий, в котором вам может понадобиться функция sleep(), а не с помощью setTimeout(), - это если у вас есть функция, реагирующая на щелчок пользователя, который в конечном итоге откроет новое всплывающее окно, и вы инициировали некоторую обработку, которая требует короткий период для заполнения до появления всплывающего окна. Перемещение открытого окна в закрытие означает, что он обычно блокируется браузером.

5

Старый вопрос с 2009 года. Теперь в 2015 году возможно новое решение с генераторами, определенными в ECMAscript 2015, а также ES6. Он был одобрен в июне, но раньше он был реализован в Firefox и Chrome. Теперь функция сна может быть сделана не занятой, неблокирующей и вложенной внутренней петлей и подфункций без замораживания браузера. Нужен только чистый JavaScript, нет библиотек или фреймворков.

В приведенной ниже программе показано, как можно сделать sleep() и runSleepyTask(). Функция sleep() - это только оператор yield. Это настолько просто, что на самом деле проще написать оператор yield непосредственно вместо вызова sleep(), но тогда не будет слова сна:-). Результат возвращает значение времени методу next() внутри wakeup() и ждет. Фактическое "спящее" выполняется в wakeup() с использованием старого старого setTimeout(). При обратном вызове метод next() запускает оператор yield для продолжения, а "магия" доходности заключается в том, что все локальные переменные и весь стек вызовов вокруг него все еще остаются нетронутыми.

Функции, которые используют sleep() или yield, должны быть определены как генераторы. Легко сделать, добавив звездочку к ключевому слову function*. Выполнять генератор немного сложнее. При вызове с ключевым словом new генератор возвращает объект, который имеет метод next(), но тело генератора не выполняется (ключевое слово new является необязательным и не имеет значения). Метод next() запускает выполнение тела генератора до тех пор, пока он не встретит yield. Функция-обертка runSleepyTask() запускает пинг-понг: next() ждет yield, а yield ждет next().

Другой способ вызвать генератор - с ключевым словом yield*, здесь он работает как простой вызов функции, но также включает возможность возврата к next().

Об этом свидетельствует пример drawTree(). Он рисует дерево с листьями на вращающейся 3D-сцене. Дерево рисуется как ствол с тремя частями вверху в разных направлениях. Затем каждая часть рисуется как другое, но меньшее дерево, вызывая drawTree() рекурсивно после короткого сна. Очень маленькое дерево рисуется только как лист.

Каждый лист имеет свою собственную жизнь в отдельной задаче, начатой ​​с runSleepyTask(). Он рождается, растет, сидит, исчезает, падает и умирает в growLeaf(). Скорость контролируется с помощью sleep(). Это демонстрирует, как легко выполнять многозадачность.

function* sleep(milliseconds) {yield milliseconds};

function runSleepyTask(task) {
    (function wakeup() {
        var result = task.next();
        if (!result.done) setTimeout(wakeup, result.value);
    })()
}
//////////////// written by Ole Middelboe  /////////////////////////////

pen3D =setup3D();
var taskObject = new drawTree(pen3D.center, 5);
runSleepyTask(taskObject);

function* drawTree(root3D, size) {
    if (size < 2) runSleepyTask(new growLeaf(root3D))
    else {
        pen3D.drawTrunk(root3D, size);
        for (var p of [1, 3, 5]) {
            var part3D = new pen3D.Thing;
            root3D.add(part3D);
            part3D.move(size).turn(p).tilt(1-p/20);
            yield* sleep(50);
            yield* drawTree(part3D, (0.7+p/40)*size);
        }
    }
}

function* growLeaf(stem3D) {
    var leaf3D = pen3D.drawLeaf(stem3D);
    for (var s=0;s++<15;) {yield* sleep(100); leaf3D.scale.multiplyScalar(1.1)}
    yield* sleep( 1000 + 9000*Math.random() );
    for (var c=0;c++<30;) {yield* sleep(200); leaf3D.skin.color.setRGB(c/30, 1-c/40, 0)}
    for (var m=0;m++<90;) {yield* sleep( 50); leaf3D.turn(0.4).tilt(0.3).move(2)}
    leaf3D.visible = false;
}
///////////////////////////////////////////////////////////////////////

function setup3D() {
    var scene, camera, renderer, diretionalLight, pen3D;

    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(75, 
        window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.set(0, 15, 20);
    renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    
    directionalLight = new THREE.DirectionalLight(0xffffaa, 0.7);
    directionalLight.position.set(-1, 2, 1);
    scene.add(directionalLight);
    scene.add(new THREE.AmbientLight(0x9999ff));
      
    (function render() {
        requestAnimationFrame(render);
        // renderer.setSize( window.innerWidth, window.innerHeight );
        scene.rotateY(10/60/60);
        renderer.render(scene, camera);
    })();
    
    window.addEventListener(
        'resize',
        function(){
            renderer.setSize( window.innerWidth, window.innerHeight );
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
       }, 
       false
    );
    
    pen3D = {
        drawTrunk: function(root, size) {
            // root.skin = skin(0.5, 0.3, 0.2);
            root.add(new THREE.Mesh(new THREE.CylinderGeometry(size/12, size/10, size, 16), 
                root.skin).translateY(size/2));
            root.add(new THREE.Mesh(new THREE.SphereGeometry(size/12, 16), 
                root.skin).translateY(size));
            return root;
        },
        
        drawLeaf: function(stem) {
            stem.skin.color.setRGB(0, 1, 0);
            stem.add(new THREE.Mesh(new THREE.CylinderGeometry(0, 0.02, 0.6), 
                stem.skin) .rotateX(0.3).translateY(0.3));
            stem.add(new THREE.Mesh(new THREE.CircleGeometry(0.2), 
                stem.skin) .rotateX(0.3).translateY(0.4));
            return stem;
        },
        
        Thing: function() {
            THREE.Object3D.call(this);
            this.skin = new THREE.MeshLambertMaterial({
                color: new THREE.Color(0.5, 0.3, 0.2),
                vertexColors: THREE.FaceColors,
                side: THREE.DoubleSide
            })
        }
    };

    pen3D.Thing.prototype = Object.create(THREE.Object3D.prototype);
    pen3D.Thing.prototype.tilt = pen3D.Thing.prototype.rotateX;
    pen3D.Thing.prototype.turn = pen3D.Thing.prototype.rotateY;
    pen3D.Thing.prototype.move = pen3D.Thing.prototype.translateY;
    
    pen3D.center = new pen3D.Thing;
    scene.add(pen3D.center);
    
    return pen3D;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>

3D-материал скрыт внутри setup3D() и включен только для того, чтобы сделать его менее скучным, чем console.log(). Кстати, ангелы измеряются в радианах.

Протестировано для работы в Firefox и Chrome. Не реализовано в Internet Explore и iOS (iPads). Попробуйте запустить его самостоятельно.

После другого ответа, который я нашел, Габриэль Ратенер сделал аналогичный ответ год назад: https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep

5

Если вы используете node.js, вы можете взглянуть на волокна - собственное расширение C для узла, своего рода многопоточное моделирование.

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

Вот свежий пример из собственного readme:

// sleep.js

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 sleep.js
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
5

В конкретном случае, когда вы хотите освободить набор вызовов, выполняемых циклом, вы можете использовать что-то вроде кода ниже с прототипом. Без прототипа вы можете заменить функцию задержки на setTimeout.

function itemHandler(item)
{
    alert(item);
}

var itemSet = ['a','b','c'];

// Each call to itemHandler will execute
// 1 second apart
for(var i=0; i<itemSet.length; i++)
{
    var secondsUntilExecution = i;
    itemHandler.delay(secondsUntilExecution, item)
}
5

Вы не можете спать, как в JavaScript, или, скорее, не должны. Запуск цикла sleep или while приведет к зависанию пользовательского браузера, пока цикл не будет выполнен.

Используйте таймер, как указано в ссылке, на которую вы ссылаетесь.

4

Начиная с узла 7.6, вы можете комбинировать функцию promisify с модулем utils с 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);
    }
  }
4

Если вы правильно выполняете функцию сна,

var sleep = function(period, decision, callback){
    var interval = setInterval(function(){
        if (decision()) {
            interval = clearInterval(interval);
            callback();
        }
    }, period);
}

и у вас есть асинхронная функция для вызова нескольких раз

var xhr = function(url, callback){
    // make ajax request
    // call callback when request fulfills
}

И вы настраиваете свой проект следующим образом:

var ready = false;

function xhr1(){
    xhr(url1, function(){ ready = true;});  
}
function xhr2(){
    xhr(url2, function(){ ready = true; }); 
}
function xhr3(){
    xhr(url3, function(){ ready = true; }); 
}

Затем вы можете сделать это:

xhr1();
sleep(100, function(){ return done; }, xhr2);
sleep(100, function(){ return done; }, xhr3);
sleep(100, function(){ return done; }, function(){
    // do more
});

Вместо бесконечного отклика обратного вызова:

xhr(url1, function(){
    xhr2(url2, function(){
        xhr3(url3, function(){
            // do more
        });
    });
});
4

Прежде всего - setTimeout и setInterval - это то, что должно, из-за характера обратного вызова javascript. Если вы хотите использовать sleep(), это управляющий поток или неправильная архитектура вашего кода.

Сказав, что, я полагаю, я все еще могу помочь с двумя реализациями сна.

  • фальсификация синхронного спуска с головы:

    //a module to do taht //dual-license: MIT or WTF [you can use it anyhow and leave my nickname in a comment if you want to]
    var _=(function(){
     var queue=[];
     var play=function(){
       var go=queue.shift();
         if(go){if(go.a){go.f();play();}else{setTimeout(play,go.t);}}
       }
     return {
       go:function(f){
        queue.push({a:1,f:f});
        },
       sleep:function(t){
        queue.push({a:0,t:t});
        },
       playback:play 
     }
    })();
    

    [сделать автоматическое воспроизведение также возможно]

    //usage
    
    _.go(function(){
    
    //your code
    console.log('first');
    
    });
    
    
    _.sleep(5000);
    
    _.go(function(){
    
    //your code
    console.log('next');
    
    });
    
    //this triggers the simulation
    _.playback();
    
  • реальный синхронный прогон

Я много думал о нем однажды, и единственная идея, которую я имел для истинного сна в javascript, является технической.

функция сна должна быть синхронным AJAX-вызовом с тайм-аутом, установленным на значение sleep. Это все и единственный способ иметь реальный sleep()

3

Если вам действительно нужен сон(), просто чтобы что-то проверить. Но имейте в виду, что это приведет к сбою браузера в большинстве случаев при отладке - возможно, именно поэтому вам это нужно. В режиме производства я прокомментирую эту функцию.

function pauseBrowser(millis) {
    var date = Date.now();
    var curDate = null;
    do {
        curDate = Date.now();
    } while (curDate-date < millis);
}

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

  • 2
    Ваш код практически совпадает с кодом в вопросе, который спрашивает, есть ли лучший способ сделать это.
  • 0
    «Это» относится к каждому. Заголовок вопроса звучит так: «Что мне делать, если я хочу JavaScript-версию sleep ()?» Использование setTimeout или setInterval включает в себя другое обоснование, которое может занять больше времени, поэтому выбор не всегда, например, для быстрого теста отладки. Кроме того, Date.now () гораздо более эффективен в памяти, чем новый Date () внутри цикла, если я не ошибаюсь.
2

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

Я выбрал пинг на несуществующем адресе.

const cp = require('child_process');

function sleep(ms)
{ 
    try{cp.execSync('ping 192.0.2.0 -n 1 -w '+ms);}
    catch(err){}
}

Тест для проверки работы

console.log(Date.now());
console.log(Date.now());
sleep(10000);
console.log(Date.now());
console.log(Date.now());

И некоторые результаты тестов.

1491575275136
1491575275157

(и через 10 секунд)

1491575285075
1491575285076
2

Это поможет вам.

var reloadAfter = 10; //seconds
var intervalId = setTimeout(function() {
    //code you want to execute after the time waiting
}, reloadAfter * 1000); // 60000 = 60 sec = 1 min
2

С поддержкой await и обещание bluebird:

await bluebird.delay(1000);

Это будет работать как синхронный sleep(1) языка c. Мое любимое решение.

  • 0
    Если у вас есть поддержка, вам не нужен Bluebird.
2

Попробуйте эту простую функцию javascript:

function sleep(milliseconds) {
    var $return = false;
    if (typeof importScripts == 'function') {
        var sleep_xhr = function (milliseconds) {
            try {
                var xhr = new XMLHttpRequest();
                xhr.open('GET', 'http://128.0.0.1:' + (Math.random() * 100000).toFixed(0) + '/', false);
                xhr.timeout = milliseconds;
                xhr.send();
            } catch (E) {
                // Nothing to do...
            }
        };
        milliseconds = milliseconds | 0;
        if (milliseconds > 0) {
            var start = Date.now();
            while (Date.now() < start + milliseconds) {
                sleep_xhr((start + milliseconds) - Date.now());
            }
            $return = Date.now() - start;
        }
    }
    return $return;
}

Примечание. Эта функция работает только с веб-рабочими.

2

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

Многие случаи могут использовать promises (AJAX требует общего использования). Они позволяют вам делать асинхронные вещи синхронно. Существует также обработка для успеха/неудачи, и они могут быть связаны цепью.

Они участвуют в ECMAScript 6, поэтому поддержка браузера еще не все, в основном, IE не поддерживает их. Существует также библиотека под названием Q для выполнения promises.

Литература: http://www.html5rocks.com/en/tutorials/es6/promises/

https://github.com/jakearchibald/es6-promise#readme (Shim для старых или IE-браузеров)

  • 0
    Это действительно должен быть комментарий, а не ответ.
2

Объявите асинхронный характер javascript!

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

Методы, которые я здесь изложил, предназначены для разных случаев использования и грубо упорядочены с точки зрения их сложности.

Различные вещи заключаются в следующем:

  • Ожидание выполнения некоторого условия
  • Ожидание набора методов для завершения (в любом порядке) перед вызовом одного обратного вызова
  • Выполнение ряда асинхронных методов с общим состоянием в определенном порядке до вызова обратного вызова

Wait

Ожидание, является ли какое-либо условие истинным, используется, когда нет доступного обратного вызова, чтобы сообщить вам, когда что-то закончило выполнение.

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

function waitFor(predicate, successCallback) {
    setTimeout(function () {
        var result = predicate();
        if (result !== undefined)
            successCallback(result);
        else
            waitFor(predicate, successCallback);
    }, 100);
}

код вызова:

    beforeEach(function (done) {
        selectListField('A field');

        waitFor(function () {
            var availableOptions = stores.scrapeStore(optionStore);
            if (availableOptions.length !== 0)
                return availableOptions;
        }, done);
    });

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

Дождитесь завершения нескольких действий

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

createWaitRunner = function (completionCallback) {
    var callback = completionCallback;
    var completionRecord = [];
    var elements = 0;

    function maybeFinish() {
        var done = completionRecord.every(function (element) {
            return element === true
        });

        if (done)
            callback();
    }

    return {
        getNotifier: function (func) {
            func = func || function (){};

            var index = elements++;
            completionRecord[index] = false;

            return function () {
                func.applyTo(arguments);
                completionRecord[index] = true;
                maybeFinish();
            }
        }
    }
};

код вызова:

    var waiter = createWaitRunner(done);

    filterList.bindStore = waiter.getNotifier();
    includeGrid.reconfigure = waiter.getNotifier(function (store) {
        includeStore = store;
    });
    excludeGrid.reconfigure = waiter.getNotifier(function (store) {
        excludeStore = store;
    });

Вы либо просто ждете уведомлений, либо можете также обернуть другие функции, которые используют значения, переданные функции. Когда все методы будут вызваны, будет выполняться done.

Выполнение асинхронных методов в порядке

Я использовал другой подход, когда у меня была серия асинхронных методов для вызова в строке (снова в тестах). Это несколько похоже на то, что вы можете получить в в библиотеке Async - серия делает примерно одно и то же, и я сначала немного читал эту библиотеку посмотрим, сделал ли он то, что я хотел. Я думаю, что у меня есть приятный api для работы с тестами, хотя (+ было интересно реализовать!).

//provides a context for running asyncronous methods syncronously
//the context just provides a way of sharing bits of state
//use run to execute the methods.  These should be methods that take a callback and optionally the context as arguments
//note the callback is provided first so you have the option of just partially applying your function to the arguments you want
//instead of having to wrap even simple functions in another function

//when adding steps you can supply either just a function or a variable name and a function
//if you supply a variable name then the output of the function (which should be passed into the callback) will be written to the context
createSynchronisedRunner = function (doneFunction) {
    var context = {};

    var currentPosition = 0;
    var steps = [];

    //this is the loop. it is triggered again when each method finishes
    var runNext = function () {
        var step = steps[currentPosition];
        step.func.call(null,
                       function (output) {
                           step.outputHandler(output);
                           currentPosition++;

                           if (currentPosition === steps.length)
                               return;

                           runNext();
                       }, context);
    };

    var api = {};

    api.addStep = function (firstArg, secondArg) {
        var assignOutput;
        var func;

        //overloads
        if (secondArg === undefined) {
            assignOutput = function () {
            };
            func = firstArg;
        }
        else {
            var propertyName = firstArg;
            assignOutput = function (output) {
                context[propertyName] = output;
            };
            func = secondArg;
        }

        steps.push({
                       func: func,
                       outputHandler: assignOutput
                   });
    };

    api.run = function (completedAllCallback) {
        completedAllCallback = completedAllCallback || function(){};

        var lastStep = steps[steps.length - 1];
        var currentHandler = lastStep.outputHandler;
        lastStep.outputHandler = function (output) {
            currentHandler(output);
            completedAllCallback(context);
            doneFunction();
        };

        runNext();
    };

    //this is to support more flexible use where you use a done function in a different scope to initialisation
    //eg the done of a test but create in a beforeEach
    api.setDoneCallback = function (done) {
        doneFunction = done;
    };

    return api;
};

код вызова:

beforeAll(function (done) {
    var runner = createSynchronisedRunner(done);
    runner.addStep('attachmentInformation', testEventService.getAttachmentCalled.partiallyApplyTo('cat eating lots of memory.jpg'));
    runner.addStep('attachment', getAttachment.partiallyApplyTo("cat eating lots of memory.jpg"));
    runner.addStep('noAttachment', getAttachment.partiallyApplyTo("somethingElse.jpg"));
    runner.run(function (context) {
        attachment = context.attachment;
        noAttachment = context.noAttachment;
    });
});

PartialApplyTo здесь, в основном, переименованная версия Doug Crockford, использующая Curry. Многие вещи, с которыми я работаю, принимают обратный вызов в качестве последнего аргумента, поэтому простые вызовы могут выполняться так, как это необходимо, вместо того, чтобы обернуть все с помощью дополнительного func.

Мы надеемся, что некоторые из этих идей могут быть полезны людям.

2

Если вам нравится советовать не проигрывать. setTimeout - ваш ожидаемый sleep. Однако, если вы хотите синтаксис, когда код "разделен по середине" на sleep, мы можем сделать:

sleep=function(tm,fn){
   window.setTimeout(fn,tm);
}

тогда, perpare выполняет следующие функции:

var fnBeforeSleep=function(){

 //All codes before sleep

}  

var fnAfterSleep=function(){

 //All codes after sleep

}  

Тогда:

fnBeforeSleep();
sleep(2000,
fnAfterSleep);

Оп! Синтаксически. Он очень близок к:

fnBeforeSleep();
sleep(2000); 
fnAfterSleep();
2

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

  • 9
    Javascript предназначен не только для веб-страниц, но и для полного перевода, который может использоваться, например, с wscript. -1 для тебя
  • 0
    Что если вы пишете служебный скрипт в Node.js и вам просто нужно подождать, прежде чем вызывать вечный инструмент или конечную точку?
Показать ещё 1 комментарий
1

Проблема с большинством решений заключается в том, что они перематывают стек. Это может быть большой проблемой в некоторых случаях. В этом примере я показываю, как использовать итераторы по-разному, чтобы имитировать реальный сон

В этом примере генератор вызывает его собственный next(), поэтому, когда он будет, он сам по себе.

var h=a();
h.next().value.r=h; //that how U run it, best I came up with

//sleep without breaking stack !!!
function *a(){
    var obj= {};

    console.log("going to sleep....2s")

    setTimeout(function(){obj.r.next();},2000)  
     yield obj;

    console.log("woke up");
    console.log("going to sleep no 2....2s")
    setTimeout(function(){obj.r.next();},2000)  
     yield obj;

     console.log("woke up");
    console.log("going to sleep no 3....2s")

     setTimeout(function(){obj.r.next();},2000) 
     yield obj;

    console.log("done");

}
1

Если вы действительно хотите приостановить script, вы можете сделать это:

var milliseconds;
var pretime;
var stage;

function step(time){
  switch(stage){
    case 0:
      //Code before the pause

      pretime=time;
      milliseconds=XXX;
      stage=1;
      break;
    case 1:
      //Code that is looped through while paused

      if(time-pretime >= milliseconds){
        //Code after the pause

        pretime=time;
        milliseconds=XXX;
        stage=2;
      }
      break;
    case 2:
      //Code that is looped through while paused

      if(time-pretime >= milliseconds){
        //Code after the pause

        pretime=time;
        milliseconds=XXX;
        stage=3;
      }
      break;
    case 3:
      //Etc...
  }

  Window.requestAnimationFrame(step)
}

step();

Это, вероятно, именно то, что вы хотите, если вы все равно используете цикл, и вы можете изменить его так, чтобы у вас была псевдо-многопоточность, где некоторые функции ждут некоторое время, а другие работают нормально. Я использую это все время для игр pure-JS.

1

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

Начиная с простой сопрограммы:

function coroutine() {
    console.log('coroutine-1:start');
    sleepFor(3000); //sleep for 3 seconds here
    console.log('coroutine-2:complete');
}

Я хочу спать 3 секунды посередине, но не хочу доминировать над всем потоком, поэтому сопрограмма должна выполняться другим потоком. Я рассматриваю Unity YieldInstruction и изменяю сопрограмму следующим образом:

function coroutine1() {
    this.a = 100;
    console.log('coroutine1-1:start');
    return sleepFor(3000).yield; // sleep for 3 seconds here
    console.log('coroutine1-2:complete');
    this.a++;
}

var c1 = new coroutine1();

Объявить прототип sleepFor:

sleepFor = function(ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?sleepFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    setTimeout(function() {
        new Function(funcArgs, funcBody).apply(context, args);
    }, ms);
    return this;
}

После запуска coroutine1 (я тестировал в IE11 и Chrome49), вы увидите, что он спал 3 секунды между двумя консольными операторами. Он сохраняет коды так же красиво, как традиционный стиль. Трудно во сне. Он читает тело функции вызывающего абонента как строку и разбивает его на две части. Удалите верхнюю часть и создайте другую функцию нижней частью. После ожидания указанного количества миллисекунд, он вызывает созданную функцию, применяя исходный контекст и аргументы. Для исходного потока он будет заканчиваться "возвратом", как обычно. Для "урожая"? Он используется для сопоставления регулярных выражений. Это необходимо, но не используется вообще.

Он не идеален на 100%, но он, по крайней мере, достигает моей работы. Я должен упомянуть некоторые ограничения в использовании этого кода. Поскольку код разбивается на 2 части, оператор "return" должен быть во внешнем, а не в любом цикле или {}. то есть.

function coroutine3() {
    this.a = 100;
    console.log('coroutine3-1:start');
    if(true) {
        return sleepFor(3000).yield;
    } // <- raise exception here
    console.log('coroutine3-2:complete');
    this.a++;
}

Вышеприведенные коды должны иметь проблему, поскольку закрытая скобка не может существовать индивидуально в созданной функции. Другим ограничением является то, что все локальные переменные, объявленные "var xxx = 123", не могут переносить на следующую функцию. Вы должны использовать "this.xxx = 123" для достижения того же. Если у вашей функции есть аргументы и они получили изменения, измененное значение также не могло переносить на следующую функцию.

function coroutine4(x) { // assume x=abc
    var z = x;
    x = 'def';
    console.log('coroutine4-1:start' + z + x); //z=abc, x=def
    return sleepFor(3000).yield;
    console.log('coroutine4-2:' + z + x); //z=undefined, x=abc
}

Я бы представил еще один прототип функции: waitFor

waitFor = function(check, ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?waitFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    var thread = setInterval(function() {
        if(check()) {
            clearInterval(thread);
            new Function(funcArgs, funcBody).apply(context, args);
        }
    }, ms?ms:100);
    return this;
}

Он ждет функцию "check", пока не вернет true. Он проверяет значение каждые 100 мс. Вы можете настроить его, передав дополнительный аргумент. Рассмотрим проверку coroutine2:

function coroutine2(c) {
    /* some codes here */
    this.a = 1;
    console.log('coroutine2-1:' + this.a++);
    return sleepFor(500).yield;

    /* next */
    console.log('coroutine2-2:' + this.a++);
    console.log('coroutine2-2:waitFor c.a>100:' + c.a);
    return waitFor(function() {
        return c.a>100;
    }).yield;

    /* the rest of code */
    console.log('coroutine2-3:' + this.a++);
}

Также в симпатичном стиле мы любим до сих пор. На самом деле я ненавижу вложенный обратный вызов. Легко понять, что coroutine2 будет ждать завершения coroutine1. Интересно? Итак, запустите следующие коды:

this.a = 10;
console.log('outer-1:' + this.a++);
var c1 = new coroutine1();
var c2 = new coroutine2(c1);
console.log('outer-2:' + this.a++);

Вывод:

outer-1:10
coroutine1-1:start
coroutine2-1:1
outer-2:11
coroutine2-2:2
coroutine2-2:waitFor c.a>100:100
coroutine1-2:complete
coroutine2-3:3

Outer немедленно завершается после инициализации coroutine1 и coroutine2. Затем coroutine1 будет ждать 3000 мс. Coroutine2 войдет в этап 2 после ожидания 500 мс. После этого он будет продолжать шаг 3 после обнаружения значений coroutine1.a > 100.

Остерегайтесь того, что существует 3 контекста для хранения переменной "a". Один из них является внешним, значения которого равны 10 и 11. Другой - в сопрограмме 1, значения которой равны 100 и 101. Последний находится в сопрограмме 2, значения которой равны 1,2 и 3. В сопрограмме 2 она также ожидает появления ca из coroutine1, пока его значение больше 100. 3 контекста независимы.

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

sleepFor = function(ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?sleepFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    setTimeout(function() {
        new Function(funcArgs, funcBody).apply(context, args);
    }, ms);
    return this;
}

waitFor = function(check, ms) {
    var caller = arguments.callee.caller.toString();
    var funcArgs = /\(([\s\S]*?)\)/gi.exec(caller)[1];
    var args = arguments.callee.caller.arguments;
    var funcBody = caller.replace(/^[\s\S]*?waitFor[\s\S]*?yield;|}[\s;]*$/g,'');
    var context = this;
    var thread = setInterval(function() {
        if(check()) {
            clearInterval(thread);
            new Function(funcArgs, funcBody).apply(context, args);
        }
    }, ms?ms:100);
    return this;
}

function coroutine1() {
    this.a = 100;
    console.log('coroutine1-1:start');
    return sleepFor(3000).yield;
    console.log('coroutine1-2:complete');
    this.a++;
}

function coroutine2(c) {
    /* some codes here */
    this.a = 1;
    console.log('coroutine2-1:' + this.a++);
    return sleepFor(500).yield;

    /* next */
    console.log('coroutine2-2:' + this.a++);
    console.log('coroutine2-2:waitFor c.a>100:' + c.a);
    return waitFor(function() {
        return c.a>100;
    }).yield;

    /* the rest of code */
    console.log('coroutine2-3:' + this.a++);
}

this.a = 10;
console.log('outer-1:' + this.a++);
var c1 = new coroutine1();
var c2 = new coroutine2(c1);
console.log('outer-2:' + this.a++);

Он протестирован в IE11 и Chrome49. Поскольку он использует arguments.callee, поэтому может возникнуть проблема, если он работает в строгом режиме.

1

Там новая библиотека, которая аккуратно цепочки функционирует вместе с таймаутами, чтобы вы могли избежать обратного вызова ада.

Sequencr.js

Включает:

setTimeout(function(timeout){
    function1();
    setTimeout(function(timeout){
        function2();
        setTimeout(function(timeout){
            function3();
        }, timeout, timeout)
    }, timeout, timeout)
}, 10, 10);

в это:

Sequencr.chain([function1, function2, function3], 10);

И имеет встроенную поддержку циклов, которые "спят" между каждой итерацией.

1

Вы можете использовать вызов закрытия setTimeout() с добавочно большими значениями.

var items = ['item1', 'item2', 'item3'];

function functionToExecute(item) {
  console.log('function executed for item: ' + item);
}

$.each(items, function (index, item) {
  var timeoutValue = index * 2000;
  setTimeout(function() {
    console.log('waited ' + timeoutValue + ' milliseconds');
    functionToExecute(item);
  }, timeoutValue);
});

Результат:

waited 0 milliseconds
function executed for item: item1
waited 2000 milliseconds
function executed for item: item2
waited 4000 milliseconds
function executed for item: item3 
  • 0
    Это отличный способ ограничить вызовы API до того, как они получат шанс кешировать. (В моем случае я отправлял несколько одинаковых почтовых индексов в API Google Geocode и кэшировал результат, были две проблемы. Цикл выполнялся бы так быстро, что первый ответ API все еще будет возвращаться, и API Google Geocode имеет скорость ограничитель только что начал бы отклонять запросы).
  • 0
    tldr; вам придется сделать что-то вроде ответа tponthieux при работе в контексте цикла. (myArray.forEach или for (i = 1; ...
Показать ещё 1 комментарий
1

Метод объекта, который должен использовать метод "сна", например:

function SomeObject() {
    this.SomeProperty = "xxx";
    return this;
}
SomeObject.prototype.SomeMethod = function () {
    this.DoSomething1(arg1);
    sleep(500);
    this.DoSomething2(arg1);
}

Можно почти перевести на:

function SomeObject() {
    this.SomeProperty = "xxx";
    return this;
}
SomeObject.prototype.SomeMethod = function (arg1) {
    var self = this;
    self.DoSomething1(arg1);
    setTimeout(function () {
        self.DoSomething2(arg1);
    }, 500);
}

Разница в том, что операция "SomeMethod" возвращается до выполнения операции "DoSomething2". Вызывающий "SomeMethod" не может зависеть от этого. Поскольку метод "Сон" не существует, я использую более поздний метод и соответствующим образом разрабатываю свой код.

Надеюсь, это поможет.

1

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

function()
{
if (!wait_condition)
    {
    setTimeout(arguments.callee, 100, /*comma-separated arguments here*/);
    }
//rest of function
}

Этот код говорит: "Если условие ожидания еще не выполнено, вызовите эту функцию снова с этими аргументами". Я использовал этот метод для передачи тем же аргументам моим обработчикам, что делает этот код незащищенным сном() (который работает только в начале вашей функции).

0

Проблема с использованием реальной функции сна состоит в том, что JavaScript является однопоточным, и функция сна в значительной степени заставит ваш браузер зависать в течение этого времени.

0

Я получил Promise не конструктор, использующий верхний ответ. Если вы импортируете Bluebird, вы можете сделать это. Самое простое решение ИМО.

import * as Promise from 'bluebird';


  await Promise.delay(5000)
0

Очень простой способ сделать сон, который БУДЕТ совместим со всем, что запускает Javascript... Этот код был протестирован с чем-то вроде 500 записей, использование ЦП и памяти до сих пор не видно в моих веб-браузерах.

Здесь одна функция, которая ждет, пока узел не станет видимым...

Эта функция создает новую контекстную function() {} чтобы избежать рекурсии. Мы поместили код, который делает то же самое, что и код вызывающей стороны, в этот новый контекст. Мы используем функцию Timeout для вызова нашей функции через несколько секунд.

var get_hyper = function (node , maxcount , only_relation) {
    if (node.offsetParent === null) {
            // node is hidden
            setTimeout(function () { get_hyper(node , maxcount , only_relation)}
                      ,1000);
            return;
    };

    // Enter here the code that wait that that the node is visible
    // before getting executed.

};
0

У меня была похожая проблема: мне пришлось ждать существования элемента управления и проверять его через определенные промежутки времени. Поскольку в JavaScript нет реального сна, ожидания или паузы и использование await/async не поддерживается должным образом в Internet Explorer, я решил использовать setTimeOut и внедрить функцию в случае успешного поиска элемента. Вот полный пример кода, поэтому каждый может воспроизвести его и использовать для собственного проекта:

<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript">
        var ElementSearchStatus = {
            None: 0,
            Found: 1,
            NotFound: 2,
            Timeout: 3
        };

        var maxTimeout = 5;
        var timeoutMiliseconds = 1000;

        function waitForElement(elementId, count, timeout, onSuccessFunction) {
            ++count;
            var elementSearchStatus = existsElement(elementId, count, timeout);
            if (elementSearchStatus == ElementSearchStatus.None) {
                window.setTimeout(waitForElement, timeoutMiliseconds, elementId, count, timeout, onSuccessFunction);
            }
            else {
                if (elementSearchStatus == ElementSearchStatus.Found) {
                    onSuccessFunction();
                }
            }
        }

        function existsElement(elementId, count, timeout) {
            var foundElements = $("#" + elementId);
            if (foundElements.length > 0 || count > timeout) {
                if (foundElements.length > 0) {
                    console.log(elementId + " found");
                    return ElementSearchStatus.Found;
                }
                else {
                    console.log("Search for " + elementId + " timed out after " + count + " tries.");
                    return ElementSearchStatus.Timeout;
                }
            }
            else {
                console.log("waiting for " + elementId + " after " + count + " of " + timeout);
                return ElementSearchStatus.None;
            }
        }

        function main() {
            waitForElement("StartButton", 0, maxTimeout, function () {
                console.log("found StartButton!");
                DoOtherStuff("StartButton2")
            });
        }

        function DoOtherStuff(elementId) {
            waitForElement(elementId, 0, maxTimeout, function () {
                console.log("found " + elementId);
                DoOtherStuff("StartButton3");
            });
        }
    </script>
</head>
<body>
    <button type="button" id="StartButton" onclick="main();">Start Test</button>
    <button type="button" id="StartButton2" onclick="alert('Hey ya Start Button 2');">Show alert</button>
</body>
</html>
0

Чтобы основной поток был занят в течение нескольких миллисекунд:

function wait(ms) {
  const start = performance.now();
  while(performance.now() - start < ms);
}
0

Функции Javascript не допускают приостановки. С синхронными процедурами Javascript реализованы. Процедуры ждут операций ввода-вывода и тайм-аутов ожидания. Доступно для javascript 1.7.

демки: демонстрационный сон демонстрационные подстановочные процедуры

0

У меня был этот вопрос в течение долгого времени, и ответ, который мне нужен, был не совсем тем, что здесь было представлено. Эта функция ожидания вызывает синхронное ожидание, которое не связывает процессор. waitForIt делает запрос ajax в любом месте и устанавливает флаг async в false. waitF делает то же самое с фреймом, и waitD делает то же самое с div. Ajax занимает около 100 мс, кадр составляет около 25, а div - около 1. Функция ожидания использует все это в зависимости от того, сколько времени вы ее дадите. Если он не стал ждать достаточно долго, сделайте это снова. Мне нужно это при работе с несколькими асинхронными элементами загрузки. В принципе, "подождите, пока этот элемент не существует". Здесь вы можете играть здесь https://jsfiddle.net/h2vm29ue/ Он просто использует то, что естественно ожидает браузер. Более длинная версия https://jsfiddle.net/5cov1p0z/32/ более точно.

 function waitForIt() {
     var start = new Date();
     var xhttp = new XMLHttpRequest();
     xhttp.onreadystatechange = function() {
         if (this.readyState == 4 && this.status == 200) {
            //doesn't matter
         }
     };
     xhttp.open("GET", "WaitForIt", false);
     xhttp.send();
     var end = new Date();
 }
 //



 function waitF() {
     var start = new Date();
     var ifram = document.createElement('iframe');
     ifram.id = 'ifram';
     ifram.src = '';
     var div = document.createElement('div');
     div.id = 'timer';
     document.body.appendChild(div);
     document.getElementById('timer').appendChild(ifram);
     document.getElementById('timer').removeChild(ifram);
     document.body.removeChild(div);
     var end = new Date();
     return (end - start);
 }


 function waitD() {
     var start = new Date();
     var div = document.createElement('div');
     div.id = 'timer';
     document.body.appendChild(div);
     div.click();
     document.body.removeChild(div);
     var end = new Date();
     return (end - start);
 }

 function wait(time) {
     var start = new Date();
     var end = new Date();
     while ((end - start < time)) {

         if ((time - (end - start)) >= 200) {
             waitForIt();
         } else {
             if ((time - (end - start)) >= 50) {
                 waitF();
             } else {
                 waitD();
             }

         }
         end = new Date();
     }
     return (end - start);
 }
0

На стороне сервера вы можете использовать метод deasync sleep(), который изначально реализован на C, чтобы он мог эффективно реализовать ждать эффекта, не блокируя цикл событий или помещая ваш процессор на 100% нагрузки.

Пример:

#!/usr/bin/env node

// Requires `npm install --save deasync`
var sleep = require("deasync").sleep;

sleep(5000);

console.log ("Hello World!!");

Но если вам нужна чистая функция javascript (например, для ее запуска на стороне клиента браузером), мне жаль, что я думаю, что ваша функция pausecomp() - это единственный способ приблизиться к ней и, более того:

  • Это останавливает не только вашу функцию, но и весь цикл событий. Таким образом, никаких других событий не будет.

  • Он ставит ваш процессор на 100% нагрузку.

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

а). Вы можете вызвать его (или вызвать функцию do_the_rest()) с таймаутом. Более простой способ, если вы не ожидаете результата от своей функции.

б). Или, если вам нужно ждать результата, вам следует перейти к использованию promises (или, конечно же, к черту callback, -)).

Нет ожидаемого результата:

function myFunc() {

    console.log ("Do some things");

    setTimeout(function doTheRest(){
        console.log ("Do more things...");
    }, 5000);

    // Returns undefined.
};


myFunc();

Пример возврата обещания (обратите внимание, что это изменяет использование вашей функции):

function myFunc(someString) {

    return new Promise(function(resolve, reject) {

        var result = [someString];
        result.push("Do some things");

        setTimeout(function(){
            result.push("Do more things...");
            resolve(result.join("\n"));
        }, 5000);

    });

};


// But notice that this approach affect to the function usage...
// (It returns a promise, not actual data):
myFunc("Hello!!").then(function(data){
    console.log(data);
}).catch(function(err){
    console.error(err);
});
0

Другой возможный способ:

var _timer;
clearTimeout(_timer);
_timer = setTimeout(function() {
    // Your code
}, 1000); // Delay for 1 s.
0

Подводя итог (как было сказано в предыдущих ответах):

В JavaScript нет встроенной функции спящего режима. Вы должны использовать setTimeout или setInterval для достижения аналогичный эффект.

Если вы действительно этого хотели, вы могли бы имитировать функцию сна с циклом for, таким как тот, который показан в исходном вопросе, но это сделает ваш процессор работать как сумасшедший. Внутри Web Worker альтернативным решением было бы сделать синхронный XMLHttpRequest невосприимчивый IP-адрес и установить правильный тайм-аут. Это позволит избежать проблемы использования ЦП. Вот пример кода:

// Works only inside a web worker

function sleep(milliseconds) {
	var req = new XMLHttpRequest();
	req.open("GET", "http://192.0.2.0/", false);
	req.timeout = milliseconds;
	try {
		req.send();
	} catch (ex) {
		
	}
}

console.log('Sleeping for 1 second...');
sleep(1000);
console.log('Slept!');

console.log('Sleeping for 5 seconds...')
sleep(5000);
console.log('Slept!');
  • 1
    хорошо, но больше невозможно: `` `Спать в течение 1 секунды ... VM1537 js: 17 Uncaught InvalidAccessError: Не удалось установить свойство 'timeout' в 'XMLHttpRequest': невозможно установить тайм-ауты для синхронных запросов, выполненных из document.sleep @ VM1537 js: 17 (анонимная функция) @ VM1537 js: 26 `` `
0

Короткий ответ: NO, а не javascript сам по себе. Вы, кажется, единственный способ не вернуть управление обратно в среду.

Это необходимо, если среда не поддерживает события. Вероятно, они тоже не поддержали бы настрой.

setimeout, безусловно, лучший способ, если вы находитесь в среде, управляемой событиями, например, браузером или node.js.

  • 0
    Это единственный правильный ответ. Спасибо.
0

Я использую многопоточный рабочий документ HTML5, который сможет прервать синхронный XMLHttpRequest, указывая на невосприимчивый URL. Это не блокирует браузер.

https://gist.github.com/el-gringo/6990785

0

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

-1

Недавно у меня был случай, когда код, следующий за обратным вызовом, выполнялся до выполнения обратного вызова $.ui.popup. Мое решение состояло в том, чтобы установить переменную до руки, называемую паузой, установить ее в true, выполнить код $.ui.popup, а затем код, который мне нужно, чтобы ждать в течение интервала. Пример:

var pause = false;
function something() {
    if(edited && renamed) {
        pause = true;
        $.ui.popup({
            //...
            doneCallback: function() {
                //...
                pause = false;
            }
            //...
        });
        //...
    }

    var waitCode = setInterval(function(){
        if(!pause) {
            //... code I needed to wait on ...
            clearInterval(waitCode);
        }
    },500);
}
-2

Я предпочитаю эту функциональную функцию sleep:

const sleep = ms =>
    Promise(resolve => setTimeout(resolve, ms))
  • 2
    Это не функция сна. Если вы вызываете функцию режима сна, она не будет ждать истечения времени, она немедленно выполнит следующие инструкции.
-2

Используйте три функции:

  1. Функция, которая вызывает setInterval для запуска цикла
  2. Функция, которая вызывает clearInterval для остановки цикла, затем вызывает setTimeout для сна и, наконец, вызывает внутри setTimeout в качестве обратного вызова для перезапуска цикла
  3. Цикл, который отслеживает количество итераций, устанавливает номер ожидания и максимальное число, вызывает функцию clearInterval после достижения номера clearInterval и вызывает clearInterval после достижения максимального числа.

var foo = {};

function main()
  {
  'use strict';
  /*Initialize global state*/
  foo.bar = foo.bar || 0;
  /* Initialize timer */ 
  foo.bop = setInterval(foo.baz, 1000); 
  }
 
 sleep = 
      function(timer)
      {
      'use strict';
      clearInterval(timer);
      timer = setTimeout(function(){main()}, 5000);
      };
       
 
 foo.baz = 
   function()
      {
      'use strict';
      /* Update state */
      foo.bar = Number(foo.bar + 1) || 0; 
      /* Log state */
      console.log(foo.bar);
      /* Check state and stop at 10 */ 
      (foo.bar === 5) && sleep(foo.bop);
      (foo.bar === 10) && clearInterval(foo.bop);
      };
      
main();

Изображение 2100

Рекомендации

-2

В Livescript (который компилируется в Javascript) вы можете сделать следующее:

sleep = (ms, func) -> set-timeout func, ms

console.log "hello-1"
<- sleep 2000ms
console.log "hello-2"
<- sleep 2000ms
console.log "hello-3"
  • 0
    это просто оборачивание setTimeout в функцию с именем sleep : p
  • 0
    да, но выглядит хорошо; право? : D
Показать ещё 1 комментарий
-2

Вот способ спящего режима в .hta script, так что при пробуждении script он выполняет следующую команду последовательно, как это необходимо в цикле. Это настоящий сон; он не удерживает процессор во время сна. Например. процессор может загружать и отображать страницы во время сна.

Только один раз, около начала кода, перейдите

var WSHShell = new ActiveXObject ("WScript.Shell");

Для сна, например. 1 секунда = 1000 миллисекунд, выполните оператор

WSHShell.Run ('Sleep.js 1000', 3, true);

В том же каталоге, что и script, находится файл Sleep.js, который содержит следующую строку:

WScript.Sleep (WScript.Arguments (0));

(Остерегайтесь; 0 находится в круглых скобках, а не в скобках.) Последняя - это линия, которая фактически выполняет сон. Аргумент true в предыдущем фрагменте делает синхронный вызов. 3 в предыдущем аргументе, похоже, не имеет никакого эффекта, но вам нужен какой-то аргумент, так что true является третьим аргументом. Microsoft говорит: "Объект WScript... никогда не нужно создавать экземпляр перед вызовом его свойств и методов, и он всегда доступен из любого файла script", но это не так. Он доступен в отдельно стоящем файле .js, таком как выше, но, по-видимому, не в файле .js, используемом файлом .hta, поэтому он должен находиться в отдельном файле, вызывается, как указано выше.

-2

Я уверен, что есть миллион способов сделать это лучше, но я думал, что попытаюсь создать объект:

// execute code consecutively with delays (blocking/non-blocking internally)
function timed_functions() 
{
this.myfuncs = [];
this.myfuncs_delays = []; // mirrors keys of myfuncs -- values stored are custom delays, or -1 for use default
this.myfuncs_count = 0; // increment by 1 whenever we add a function
this.myfuncs_prev   = -1; // previous index in array
this.myfuncs_cur    = 0; // current index in array
this.myfuncs_next  = 0; // next index in array
this.delay_cur     = 0; // current delay in ms
this.delay_default = 0; // default delay in ms
this.loop = false;      // will this object continue to execute when at end of myfuncs array?
this.finished = false;  // are we there yet?
this.blocking = true;   // wait till code completes before firing timer?
this.destroy = false;   // <advanced> destroy self when finished


this.next_cycle = function() {
var that  = this;
var mytimer = this.delay_default;

if(this.myfuncs_cur > -1)
if(this.myfuncs_delays[this.myfuncs_cur] > -1)
mytimer = this.myfuncs_delays[this.myfuncs_cur];

console.log("fnc:" + this.myfuncs_cur);
console.log("timer:" + mytimer);
console.log("custom delay:" + this.myfuncs_delays[this.myfuncs_cur]);
setTimeout(function() {
// times up! next cycle...
that.cycle(); 

}, mytimer);
}

this.cycle = function() {

// now check how far we are along our queue.. is this the last function?
if(this.myfuncs_next + 1 > this.myfuncs_count)
{
if(this.loop)
{
console.log('looping..');
this.myfuncs_next = 0;
}
else
this.finished = true;
}


// first check if object isn't finished
if(this.finished)
return false;

// HANDLE NON BLOCKING //
if(this.blocking != true) // blocking disabled
{
console.log("NOT BLOCKING");
this.next_cycle();
}


// set prev = current, and current to next, and next to new next
this.myfuncs_prev = this.myfuncs_cur;
this.myfuncs_cur  = this.myfuncs_next;
this.myfuncs_next++; 

// execute current slot
this.myfuncs[this.myfuncs_cur]();




// HANDLE BLOCKING
if(this.blocking == true)  // blocking enabled
{
console.log("BLOCKING");
this.next_cycle();
}




return true;
};

// adders 
this.add = {
that:this,

fnc: function(aFunction) { 
// add to the function array
var cur_key = this.that.myfuncs_count++;
this.that.myfuncs[cur_key] = aFunction;
// add to the delay reference array
this.that.myfuncs_delays[cur_key] = -1;
}
}; // end::this.add

// setters
this.set = {
that:this, 

delay:          function(ms)    {  
var cur_key = this.that.myfuncs_count - 1;
// this will handle the custom delay array this.that.myfunc_delays
// add a custom delay to your function container

console.log("setting custom delay. key: "+ cur_key + " msecs: " + ms);
if(cur_key > -1)
{ 
this.that.myfuncs_delays[cur_key] = ms; 
}

// so now we create an entry on the delay variable
},  

delay_cur:      function(ms)    { this.that.delay_cur = ms;         },
delay_default:  function(ms)    { this.that.delay_default = ms;         },
loop_on:          function()        { this.that.loop = true; }, 
loop_off:         function()        { this.that.loop = false; },
blocking_on:      function()        { this.that.blocking = true; }, 
blocking_off:     function()        { this.that.blocking = false; },

finished:           function(aBool) { this.that.finished = true; }
}; // end::this.set    


// setters
this.get = {
that:this, 

delay_default: function() { return this.that.delay_default; },
delay_cur:     function() { return this.that.delay_cur; }
}; // end::this.get     

} // end:::function timed_functions()

и используйте как:   //////BEGIN:: TEST//////

// initialize
var fncTimer = new timed_functions;

// set some defaults
fncTimer.set.delay_default(1000);
fncTimer.set.blocking_on();
// fncTimer.set.loop_on();
// fncTimer.set.loop_off();


// BEGIN :: ADD FUNCTIONS (they will fire off in order)
fncTimer.add.fnc(function() {
    console.log('plan a (2 secs)');
});
fncTimer.set.delay(2000); // set custom delay for previously added function

fncTimer.add.fnc(function() {
    console.log('hello world (delay 3 seconds)');
});
fncTimer.set.delay(3000);

fncTimer.add.fnc(function() {
    console.log('wait 4 seconds...');
});
fncTimer.set.delay(4000);

fncTimer.add.fnc(function() {
    console.log('wait 2 seconds');
});
fncTimer.set.delay(2000);

fncTimer.add.fnc(function() {
    console.log('finished.');
});
// END :: ADD FUNCTIONS


// NOW RUN
fncTimer.cycle(); // begin execution 


// // // END :: TEST // // //
-3

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

const { promisify } = require('util')
const sleep = promisify(setTimeout)

module.exports = () => {
  await someAsyncFunction()
  await sleep(2000)
  console.log('2 seconds later...')
}
  • 0
    вы не можете использовать await внутри не async функции (в вашем примере это экспортированная функция)
-3

Возможно, я немного опоздаю, немного ленив и немного скучен или немного навязчив или немного похож на "назад, bigmouth", но...

Каждое и любое решение, которое я прочитал до сих пор, было бы "поспать и посмотреть, что случилось, завтра".

setInterval (callback, time) будет долго ждать, а затем вызывает обратный вызов, WHILE блокирует время выполнения. Текущая реализация "setInterval" далека от экономии потоков, даже для ума concurrency.

Пока упоминаются разреженные решения, предположите, что, С# (смеется), они все еще не работают, как в С#/. NET. Они все еще работают, как в C.

В настоящее время JavaScript НЕ предоставляет архитектуру для выполнения реальной многопоточности. Лучшим подходом было бы TypeScript, но все же этому недостает такого реального решения, которое оно... болит. JavaScript, jQuery и AJAX, а также jNode и даже TypeScript - это всего лишь куча Wannabes, полагающаяся на товар и плохое настроение разработчиков. Факт. Полная остановка.

-5

Это может сработать. Это сработало для меня в c и javascript.

function sleep(time) {
 var x = 0;
 for(x = 0;x < time;x++) {/* Do nothing*/}
}
  • 0
    Следует избегать использования for / while / foreach в javascript. setInverval() этого рассмотрите setTimeout() или setInverval()
-6

переключитесь на php и вставьте это, где вы нужен он

<?php sleep(4); ?>

нет необходимости воссоздавать колесо

-6
var waitTillSomethingHappens = function(){  
    if(somethingHappened == 1)  
    {  
        alert('Something Happened get out of sleep');  
    }
    else
    {  
    setTimeout(waitTillSomethingHappens,1000);  
    }  
};
  • 1
    Это не отвечает на вопрос. Вы не объяснили (или где показаны определение) вашу somethingHappened функции.
  • 0
    Если бы somethingHappened было somethingHappened как функция, то оповещение никогда не вызывалось бы, потому что оно никогда не было бы равным 1. Действительно, этот пример не должен говорить == 1 потому что он должен быть просто условием-заполнителем, и потому что вы не должны использовать числа в качестве логических значений и даже если вы, вам не нужно == 1 .
-6

Или просто создайте это:

function yourFunction(){

   //do something
   setInterval(myFunc(),1000);
   //do something else

}

function myFunc(){
   return;
}

это просто подождет указанный интервал и вызовет функцию, которая просто ничего не сделает.

  • 0
    setInterval будет часто вызывать функцию после завершения таймера
  • 2
    setInterval () создаст форк и будет продолжать вызывать функцию каждые 1000 мс. Но это не остановит исполнение. Это означает, // do something else будет немедленно продолжено.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню