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

Вы можете использовать общий (общий) метод для чтения атрибута над данным MemberInfo

public static bool TryGetAttribute<T>(MemberInfo memberInfo, out T customAttribute) where T: Attribute {
                var attributes = memberInfo.GetCustomAttributes(typeof(T), false).FirstOrDefault();
                if (attributes == null) {
                    customAttribute = null;
                    return false;
                }
                customAttribute = (T)attributes;
                return true;
            }
1946
задан 12 revs, 10 users 38% 17 March 2018 в 18:15
поделиться

70 ответов

Если вы используете 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');
67
ответ дан Alan Plum 17 March 2018 в 18:15
поделиться

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

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

Это, вероятно, самое близкое к тому, что просто делает то, что вы хотите.

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

16
ответ дан Mainguy 17 March 2018 в 18:15
поделиться

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

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

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

10
ответ дан Homer6 17 March 2018 в 18:15
поделиться

Недавно у меня был случай, когда код, следующий за обратным вызовом, выполнялся до выполнения обратного вызова из $.ui.popup. Мое решение состояло в том, чтобы установить переменную перед рукой, называемой pause, установить ее в 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);
}
-1
ответ дан gattsbr 17 March 2018 в 18:15
поделиться

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

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

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

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

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

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

Редактировать

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

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

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

171
ответ дан DevinB 17 March 2018 в 18:15
поделиться

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

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

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

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

43
ответ дан 4 revs, 3 users 46% 17 March 2018 в 18:15
поделиться

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

// 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) {}
}
30
ответ дан Ian Maddox 17 March 2018 в 18:15
поделиться
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
8
ответ дан Shemeer M Ali 17 March 2018 в 18:15
поделиться

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

120
ответ дан 5 revs, 2 users 83% 17 March 2018 в 18:15
поделиться

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

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

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
ответ дан Ivan 17 March 2018 в 18:15
поделиться

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

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

тогда:

sleep(2); // Sleeps for 2 seconds

Я использую его все время, чтобы создать ложное время загрузки при создании сценариев в P5js

19
ответ дан Akelian 17 March 2018 в 18:15
поделиться

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

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

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 !"); }
285
ответ дан 2 revs, 2 users 96% 17 March 2018 в 18:15
поделиться

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

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

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

3
ответ дан Rodrigo 17 March 2018 в 18:15
поделиться

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

2
ответ дан Scimon 17 March 2018 в 18:15
поделиться

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

  1. Функция, которая вызывает setInterval для запуска цикла
  2. Функция, которая вызывает clearInterval для остановки цикла, а затем вызывает setTimeout в сон, и, наконец, вызовы внутри setTimeout в качестве обратного вызова для перезапуска цикла.
  3. Цикл, который отслеживает количество итераций, устанавливает число сна и максимальное число, вызывает функцию сна после сна номер был достигнут и звонит 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();

Event Loop

Ссылки

-1
ответ дан 4 revs 17 March 2018 в 18:15
поделиться

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

6
ответ дан naazgull 17 March 2018 в 18:15
поделиться

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

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
ответ дан BishopZ 17 March 2018 в 18:15
поделиться

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

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

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

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

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

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

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

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

-2
ответ дан 2 revs 17 March 2018 в 18:15
поделиться

Для конкретного случая, когда требуется разметить набор вызовов, выполняемых циклом, вы можете использовать что-то вроде приведенного ниже кода с прототипом. Без прототипа вы можете заменить функцию задержки на 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
ответ дан beauburrier 17 March 2018 в 18:15
поделиться

Если вам нравится совет, чтобы не потерять производительность. setTimeout ваш ожидаемый sleep. Однако, если вы хотите использовать синтаксис, в котором код «делится на середину» на sleep, мы можем сделать:

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

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

var fnBeforeSleep=function(){

 //All codes before sleep

}  

var fnAfterSleep=function(){

 //All codes after sleep

}  

Тогда :

fnBeforeSleep();
sleep(2000,
fnAfterSleep);

Да! ٍ синтаксически, это очень близко к:

fnBeforeSleep();
sleep(2000); 
fnAfterSleep();
2
ответ дан Abdennour TOUMI 17 March 2018 в 18:15
поделиться

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

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

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

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

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

842
ответ дан 4 revs, 3 users 67% 17 March 2018 в 18:15
поделиться

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

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

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

6
ответ дан caiocpricci2 17 March 2018 в 18:15
поделиться

Код, взятый из этой ссылки , не замораживает комп. Но это работает только на ff.

/**
 * Netscape compatible WaitForDelay function.
 * You can use it as an alternative to Thread.Sleep() in any major programming language
 * that support it while JavaScript it self doesn't have any built-in function to do such a thing.
 * parameters:
 * (Number) delay in millisecond
 */
function nsWaitForDelay(delay) {
    /**
     * Just uncomment this code if you're building an extention for Firefox.
     * Since FF3, we'll have to ask for user permission to execute XPCOM objects.
     */
    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");

    // Get the current thread.
    var thread = Components.classes["@mozilla.org/thread-manager;1"].getService(Components.interfaces.nsIThreadManager).currentThread;

    // Create an inner property to be used later as a notifier.
    this.delayed = true;

    /* Call JavaScript setTimeout function
      * to execute this.delayed = false
      * after it finish.
      */
    setTimeout("this.delayed = false;", delay);

    /**
     * Keep looping until this.delayed = false
     */
    while (this.delayed) {
        /**
         * This code will not freeze your browser as it's documented in here:
         * https://developer.mozilla.org/en/Code_snippets/Threads#Waiting_for_a_background_task_to_complete
         */
        thread.processNextEvent(true);
    }
}
4
ответ дан 2 revs, 2 users 74% 17 March 2018 в 18:15
поделиться

Это можно сделать с помощью метода сна Java. Я протестировал его в 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();

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

6
ответ дан Rachael 17 March 2018 в 18:15
поделиться

Начиная с узла 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
ответ дан Harry 17 March 2018 в 18:15
поделиться

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

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

5
ответ дан Andrew Dunkman 17 March 2018 в 18:15
поделиться

Если вы используете node.js, вы можете взглянуть на fiber - собственное расширение 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
ответ дан tomekwi 17 March 2018 в 18:15
поделиться

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

function yourFunction(){

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

}

function myFunc(){
   return;
}

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

-6
ответ дан FaTaL_ErRoR 17 March 2018 в 18:15
поделиться

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

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

// ......................................... // пример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>

// .................................... // example2 :

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

// ................. пример3:

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

// ........ ...... пример4:

<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>
8
ответ дан user207408 17 March 2018 в 18:15
поделиться

Примите асинхронную природу javascript!

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

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

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

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

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

    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 'store' и ждет, пока хранилище содержит что-то перед продолжением (beforeEach - это фреймворк для тестирования жасмина).

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

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

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

    PartiallyApplyTo здесь в основном переименованная версия реализации Curry Дуга Крокфорда. Многое из того, с чем я работаю, принимает в качестве последнего аргумента обратный вызов, поэтому простые вызовы можно выполнять, как это, вместо того, чтобы оборачивать все с помощью дополнительной функции.

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

2
ответ дан JonnyRaa 17 March 2018 в 18:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: